var Testopia = {};
Testopia.Attachment = {};
Testopia.Build = {};
Testopia.TestCase = {};
Testopia.TestCase.Bugs = {};
Testopia.TestCaseRun = {};
Testopia.Category = {};
Testopia.Environment = {};
Testopia.TestPlan = {};
Testopia.TestRun = {};
Testopia.Search = {};
Testopia.Tags = {};
Testopia.Util = {};
Testopia.Product = {};
Testopia.User = {};
Testopia.Search.dashboard_urls = [];
Ext.state.Manager.setProvider(new Ext.state.CookieProvider({
expires: new Date(new Date().getTime() + (1000 * 60 * 60 * 24 * 30))
}));
Ext.data.Connection.timeout = 120000;
Ext.Updater.defaults.timeout = 120000;
Ext.Ajax.timeout = 120000;
Ext.BLANK_IMAGE_URL = 'extensions/testopia/extjs/resources/images/default/s.gif'; 
Ext.override(Ext.form.Field, {
fireKey: function(e){
if (((Ext.isIE && e.type == 'keydown') || e.type == 'keypress') && e.isSpecialKey()) {
this.fireEvent('specialkey', this, e);
}
else {
this.fireEvent(e.type, this, e);
}
},
initEvents: function(){
this.el.on("focus", this.onFocus, this);
this.el.on("blur", this.onBlur, this);
this.el.on("keydown", this.fireKey, this);
this.el.on("keypress", this.fireKey, this);
this.el.on("keyup", this.fireKey, this);
this.originalValue = this.getValue();
}
});// End Override
Ext.override(Ext.menu.Menu, {
ignoreParentClicks: true,
enableScrolling: false
});
Ext.grid.CheckColumn = function(config){
Ext.apply(this, config);
if (!this.id) {
this.id = Ext.id();
}
this.renderer = this.renderer.createDelegate(this);
};
Ext.grid.CheckColumn.prototype = {
init: function(grid){
this.grid = grid;
this.grid.on('render', function(){
var view = this.grid.getView();
view.mainBody.on('mousedown', this.onMouseDown, this);
}, this);
},
onMouseDown: function(e, t){
if (t.className && t.className.indexOf('x-grid3-cc-' + this.id) != -1) {
e.stopEvent();
var index = this.grid.getView().findRowIndex(t);
var record = this.grid.store.getAt(index);
record.set(this.dataIndex, !record.data[this.dataIndex]);
}
},
renderer: function(v, p, record){
p.css += ' x-grid3-check-col-td';
return '<div class="x-grid3-check-col' + (v == '1' ? '-on' : '') + ' x-grid3-cc-' + this.id + '">&#160;</div>';
}
};
var imgButtonTpl = new Ext.Template('<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>' +
'<td><button type="button"><img src="{0}"></button></td>' +
'</tr></tbody></table>');
Testopia.Attachment.Grid = function(object){
function attachlink(id){
return '<a href="tr_attachment.cgi?attach_id=' + id + '">' + id + '</a>';
}
this.object = object;
this.store = new Ext.data.JsonStore({
url: 'tr_attachment.cgi',
root: 'attachment',
listeners: { 'exception': Testopia.Util.loadError },
baseParams: {
ctype: 'json',
action: 'list',
object: this.object.type,
object_id: this.object.id
},
id: 'attach_id',
fields: [{
name: "attach_id",
mapping: "attachment_id"
}, {
name: "submitter",
mapping: "submitter"
}, {
name: "caserun_id",
mapping: "caserun_id"
}, {
name: "filename",
mapping: "filename"
}, //editable
{
name: "timestamp",
mapping: "creation_ts"
}, {
name: "mimetype",
mapping: "mime_type"
}, //editable
{
name: "description",
mapping: "description"
}, //editable
{
name: "isviewable",
mapping: "isviewable"
}, {
name: "canedit",
mapping: "canedit"
}, {
name: "candelete",
mapping: "candelete"
}, {
name: "size",
mapping: "datasize"
}]
});
var ds = this.store;
this.columns = [{
id: 'attach_id',
header: "ID",
width: 20,
sortable: true,
dataIndex: 'attach_id',
renderer: attachlink
}, {
header: "Created",
width: 50,
sortable: true,
dataIndex: 'timestamp',
renderer: function(v, md, r){
if (r.get('caserun_id') && Ext.getCmp('caserun_grid') && Ext.getCmp('caserun_grid').getSelectionModel().getSelected().get('caserun_id') == r.get('caserun_id')) {
return '<b>* ' + v + '</b>'; 
}
else {
return v;
}
}
}, {
header: "Name",
width: 50,
editor: {
xtype: 'textfield'
},
sortable: true,
dataIndex: 'name'
}, {
header: "Submitted by",
width: 50,
sortable: true,
dataIndex: 'submitter'
}, {
header: "Type",
width: 30,
editor: {
xtype: 'textfield'
},
sortable: true,
dataIndex: 'mimetype'
}, {
header: "Description",
width: 120,
editor: {
xtype: 'textfield',
value: 'description'
},
sortable: true,
dataIndex: 'description'
}, {
header: "Size",
width: 50,
sortable: true,
dataIndex: 'size',
renderer: function(v){
if (v) 
return v + ' Bytes';
}
}];
this.form = new Ext.form.BasicForm('testopia_helper_frm', {});
Testopia.Attachment.Grid.superclass.constructor.call(this, {
title: 'Attachments',
id: 'attachments_panel',
loadMask: {
msg: 'Loading attachments...'
},
autoExpandColumn: "Name",
autoScroll: true,
plugins: [new Ext.ux.grid.RowEditor({
id:'attachment_row_editor',
saveText: 'Update'
})],
enableColumnHide: true,
tbar: ['->', {
xtype: 'button',
id: 'edit_attachment_btn',
icon: 'extensions/testopia/img/edit.png',
iconCls: 'img_button_16x',
disabled: true,
tooltip: 'Edit Attachments',
handler: function(){
Testopia.Util.editFirstSelection(Ext.getCmp('attachments_panel'));
}
}, {
xtype: 'button',
id: 'add_attachment_btn',
icon: 'extensions/testopia/img/add.png',
iconCls: 'img_button_16x',
tooltip: 'Attach a new file',
handler: this.newAttachment.createDelegate(this)
}, {
xtype: 'button',
id: 'delete_attachment_btn',
icon: 'extensions/testopia/img/delete.png',
iconCls: 'img_button_16x',
disabled: true,
tooltip: 'Remove selected attachments',
handler: this.deleteAttachment.createDelegate(this)
}],
sm: new Ext.grid.RowSelectionModel({
singleSelect: false,
listeners: {
'rowselect': function(sm, i, r){
if (r.get('candelete')) {
Ext.getCmp('delete_attachment_btn').enable();
}
if (r.get('canedit')) {
Ext.getCmp('edit_attachment_btn').enable();
}
},
'rowdeselect': function(sm, i, r){
if (sm.getCount() < 1) {
Ext.getCmp('delete_attachment_btn').disable();
Ext.getCmp('edit_attachment_btn').disable();
}
}
}
}),
viewConfig: {
forceFit: true
}
});
this.on('rowcontextmenu', this.onContextClick, this);
this.on('activate', this.onActivate, this);
Ext.getCmp('attachment_row_editor').on('afteredit', this.onGridEdit, this);
};
Ext.extend(Testopia.Attachment.Grid, Ext.grid.GridPanel, {
onContextClick: function(grid, index, e){
var sm = this.selectionModel;
var object = this.object;
if (!this.menu) { // create context menu on first right click
this.menu = new Ext.menu.Menu({
id: 'AttachGrid-ctx-menu',
enableScrolling: false,
items: [{
text: "Delete Selected Attachments",
id: 'attach_delete_mnu',
icon: 'extensions/testopia/img/delete.png',
iconCls: 'img_button_16x',
disabled: true,
handler: this.deleteAttachment.createDelegate(this)
}, {
text: 'Reload List',
handler: function(){
grid.store.reload();
}
}]
});
}
e.stopEvent();
if (grid.getSelectionModel().getCount() < 1) {
grid.getSelectionModel().selectRow(index);
}
if (grid.getSelectionModel().getSelected().get('candelete')) {
Ext.getCmp('attach_delete_mnu').enable();
}
else {
Ext.getCmp('attach_delete_mnu').enable();
}
this.menu.showAt(e.getXY());
},
onGridEdit: function(e){
var myparams = e.record.data;
var ds = this.store;
myparams.ctype = 'json';
myparams.action = 'edit';
this.form.submit({
url: "tr_attachment.cgi",
params: myparams,
success: function(f, a){
ds.commitChanges();
},
failure: function(f, a){
Testopia.Util.error(f, a);
ds.rejectChanges();
}
});
},
newAttachment: function(){
var form = new Testopia.Attachment.NewAttachmentPopup(this.object);
form.window.show();
},
deleteAttachment: function(){
object = this.object;
Ext.Msg.show({
title: 'Confirm Delete?',
msg: ATTACHMENT_DELETE_WARNING,
buttons: Ext.Msg.YESNO,
fn: function(btn){
if (btn == 'yes') {
var testopia_form = new Ext.form.BasicForm('testopia_helper_frm');
testopia_form.submit({
url: 'tr_attachment.cgi',
params: {
attach_ids: Testopia.Util.getSelectedObjects(Ext.getCmp('attachments_panel'), 'id'),
action: 'remove',
ctype: 'json',
object: object.type,
object_id: object.id
},
success: function(){
Ext.getCmp('attachments_panel').store.load();
},
failure: Testopia.Util.error
});
}
},
animEl: 'delete_attachment_btn',
icon: Ext.MessageBox.QUESTION
});
},
onActivate: function(event){
if (this.object.type == 'caserun') {
this.store.baseParams = {
ctype: 'json',
action: 'list',
object: 'caserun',
object_id: Ext.getCmp('caserun_grid').getSelectionModel().getSelected().get('caserun_id')
};
this.store.load();
}
if (!this.store.getCount()) {
this.store.load();
}
}
});
Testopia.Attachment.Form = function(){
var filecount = 1;
Testopia.Attachment.Form.superclass.constructor.call(this, {
title: "Attachments",
id: 'attachments_form',
autoScroll: true,
items: [{
layout: 'column',
items: [{
columnWidth: 0.5,
layout: 'form',
bodyStyle: 'padding: 5px 5px 10px 10px',
id: 'attach_file_col',
items: [{
xtype: 'field',
fieldLabel: 'Attachment',
inputType: 'file',
name: 'file1',
width: 300
}]
}, {
columnWidth: 0.5,
id: 'attach_desc_col',
bodyStyle: 'padding: 5px 5px 10px 10px',
layout: 'form',
items: [{
xtype: 'textfield',
fieldLabel: 'Description',
name: 'file_desc1',
width: 300
}]
}]
}],
buttons: [{
text: 'Attach Another',
handler: function(){
filecount++;
if (filecount > 4) {
Ext.Msg.show({
msg: 'You may only attach 4 files at a time',
title: 'Limit Exceeded',
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.WARNING
});
return;
}
Ext.getCmp('attach_file_col').add(new Ext.form.Field({
fieldLabel: 'Attachment',
inputType: 'file',
name: 'file' + filecount,
width: 300
}));
Ext.getCmp('attach_desc_col').add(new Ext.form.Field({
fieldLabel: 'Description',
name: 'file_desc' + filecount,
width: 300
}));
Ext.getCmp('attachments_form').doLayout();
}
}]
});
this.on('activate', this.onActivate, this);
};
Ext.extend(Testopia.Attachment.Form, Ext.Panel, {
onActivate: function(){
Ext.getCmp('attachments_form').doLayout();
}
});
Testopia.Attachment.NewAttachmentPopup = function(object){
if (!this.window) {
var win = new Ext.Window({
id: 'new_attachment_win',
title: 'Attach a file',
closable: true,
width: 400,
height: 180,
plain: true,
shadow: false,
closable: false,
layout: 'fit',
items: [{
xtype: 'form',
id: 'new_attach_frm',
fileUpload: true,
bodyStyle: 'padding: 10px',
items: [{
xtype: 'textfield',
id: 'attach_desc',
fieldLabel: 'Description',
name: 'description',
allowBlank: false
}, {
xtype: 'field',
id: 'attach_file',
inputType: 'file',
fieldLabel: 'File',
name: 'data',
allowBlank: false               
}]
}],
buttons: [{
text: 'Submit',
handler: function(){
Ext.getCmp('new_attach_frm').getForm().submit({
url: 'tr_attachment.cgi',
params: {
action: 'add',
object: object.type,
object_id: object.id,
ctype: 'json'
},
success: function(){
Ext.getCmp('attachments_panel').store.load();
Ext.getCmp('new_attachment_win').close();
},
failure: Testopia.Util.error
});
}
}, {
text: 'Cancel',
handler: function(){
Ext.getCmp('new_attachment_win').close();
}
}]
});
this.window = win;
}
return this;
};
Testopia.Build.Store = function(params, auto){
params.action = 'list';
Testopia.Build.Store.superclass.constructor.call(this, {
url: 'tr_builds.cgi',
root: 'builds',
listeners: { 'exception': Testopia.Util.loadError },
baseParams: params,
id: 'build_id',
autoLoad: auto,
fields: [{
name: "build_id",
mapping: "build_id"
}, {
name: "name",
mapping: "name"
}, {
name: "milestone",
mapping: "milestone"
}, {
name: "description",
mapping: "description"
}, {
name: "product_id",
mapping: "product_id"
}, {
name: "isactive",
mapping: "isactive"
}]
});
};
Ext.extend(Testopia.Build.Store, Ext.data.JsonStore);
Testopia.Build.Combo = function(cfg){
Testopia.Build.Combo.superclass.constructor.call(this, {
id: cfg.id || 'build_combo',
store: cfg.transform ? false : new Testopia.Build.Store(cfg.params, cfg.mode == 'local' ? true : false),
loadingText: 'Looking up builds...',
displayField: 'name',
valueField: 'build_id',
typeAhead: true,
triggerAction: 'all',
minListWidth: 300,
forceSelection: true,
transform: cfg.transform,
emptyText: 'Builds...'
});
Ext.apply(this, cfg);
this.store.on('load', function(){
if (cfg.value) {
this.setValue(cfg.value);
}
}, this);
};
Ext.extend(Testopia.Build.Combo, Ext.form.ComboBox);
Testopia.Build.Grid = function(product_id){
this.product_id = product_id;
this.store = new Testopia.Build.Store({}, false);
var mbox = new Testopia.Product.MilestoneCombo({
hiddenField: 'milestone',
mode: 'remote',
params: {
product_id: product_id
},
listeners: {
'startedit': function(){
var pid = Ext.getCmp('products_pane').getSelectionModel().getSelectedNode().id;
if (mbox.store.baseParams.product_id != pid) {
mbox.store.baseParams.product_id = pid;
mbox.store.load();
}
}
}
});
this.columns = [{
header: "Name",
width: 80,
sortable: true,
dataIndex: 'name',
editor: {
xtype: 'textfield',
value: 'name',
allowBlank: false
}
}, {
header: "Description",
width: 120,
editor: {
xtype: 'textfield'
},
sortable: true,
dataIndex: 'description'
}, {
header: "Milestone",
width: 120,
sortable: true,
dataIndex: 'milestone',
editor: mbox
}, {
header: 'Active',
dataIndex: 'isactive',
trueText: 'Yes',
falseText: 'No',
sortable: true,
xtype: 'booleancolumn',
editor:{
xtype: 'checkbox',
value: 'isactive'
},
width: 25
}];
this.form = new Ext.form.BasicForm('testopia_helper_frm');
Testopia.Build.Grid.superclass.constructor.call(this, {
title: 'Builds',
id: 'build_grid',
loadMask: {
msg: 'Loading Builds...'
},
autoExpandColumn: "build_name",
autoScroll: true,
plugins: [new Ext.ux.grid.RowEditor({
id:'build_row_editor',
saveText: 'Update'
})],
sm: new Ext.grid.RowSelectionModel({
singleSelect: true
}),
viewConfig: {
forceFit: true
},
tbar: [new Ext.Toolbar.Fill(), {
xtype: 'button',
id: 'edit_build_btn',
icon: 'extensions/testopia/img/edit.png',
iconCls: 'img_button_16x',
tooltip: 'Edit Selected Build',
handler: function(){
Testopia.Util.editFirstSelection(Ext.getCmp('build_grid'));
}
}, {
xtype: 'button',
id: 'add_build_btn',
icon: 'extensions/testopia/img/add.png',
iconCls: 'img_button_16x',
tooltip: 'Add a new Build',
handler: this.newRecord
}]
});
this.on('rowcontextmenu', this.onContextClick, this);
this.on('activate', this.onActivate, this); 
Ext.getCmp('build_row_editor').on('afteredit', this.onGridEdit, this);
};
Ext.extend(Testopia.Build.Grid, Ext.grid.GridPanel, {
newRecord: function(){
NewBuild = Ext.data.Record.create([{
name: 'name',
type: 'string'
}, {
name: 'milestone'
}, {
name: 'description',
type: 'string'
}, {
name: 'isactive',
type: 'bool'
}]);
var b = new NewBuild({
name: '',
milestone: Ext.getCmp('products_pane').getSelectionModel().getSelectedNode().attributes.attributes.defaultmilestone,
description: '',
isactive: true
});
var g = Ext.getCmp('build_grid');
g.store.insert(0, b);
Ext.getCmp('build_row_editor').startEditing(0);
},
onContextClick: function(grid, index, e){
grid.getSelectionModel().selectRow(index);
if (!this.menu) { // create context menu on first right click
this.menu = new Ext.menu.Menu({
id: 'build-ctx-menu',
enableScrolling: false,
items: [{
text: "Reports",
enableScrolling: false,
menu: {
items: [{
text: 'New Completion Report',
handler: function(){
Ext.getCmp('object_panel').setActiveTab('dashboardpanel');
var newPortlet = new Ext.ux.Portlet({
title: 'Build Completion Report',
closable: true,
autoScroll: true,
tools: PortalTools
});
newPortlet.url = 'tr_builds.cgi?action=report&product_id=' + grid.product_id + '&build_ids=' + Testopia.Util.getSelectedObjects(grid, 'id');
Testopia.Search.dashboard_urls.push(newPortlet.url);
Ext.getCmp('dashboard_leftcol').add(newPortlet);
Ext.getCmp('dashboard_leftcol').doLayout();
newPortlet.load({
url: newPortlet.url
});
}
}]
}
}, {
text: 'Add a Build', 
icon: 'extensions/testopia/img/add.png',
iconCls: 'img_button_16x',
handler: this.newRecord
}, {
text: 'Edit This Build', 
icon: 'extensions/testopia/img/edit.png',
iconCls: 'img_button_16x',
handler: function(){
Testopia.Util.editFirstSelection(grid);
}
}, {
text: 'Refresh',
icon: 'extensions/testopia/img/refresh.png',
iconCls: 'img_button_16x',
handler: function(){
grid.store.reload();
} 
}]
});
}
e.stopEvent();
this.menu.showAt(e.getXY());
},
onGridEdit: function(e){
var myparams = e.record.data;
var ds = this.store;
myparams.product_id = this.product_id;
if (myparams.build_id) {
myparams.action = "edit";
}
else {
myparams.action = "add";
}
this.form.submit({
url: "tr_builds.cgi",
params: myparams,
success: function(f, a){
if (a.result.build_id) {
e.record.set('build_id', a.result.build_id);
}
ds.commitChanges();
},
failure: function(f, a){
Testopia.Util.error(f, a);
ds.rejectChanges();
}
});
},
onActivate: function(event){
if (!this.product_id) {
Ext.Msg.alert('Error', 'Please select a product.');
Ext.getCmp('edit_build_btn').disable();
Ext.getCmp('add_build_btn').disable();
return;
}
else {
if (!this.store.getCount()) {
this.store.load({
params: {
product_id: this.product_id
}
});
}
}
}
});
Testopia.TestCase.Store = function(params, auto){
Testopia.TestCase.Store.superclass.constructor.call(this, {
url: 'tr_list_cases.cgi',
baseParams: params,
listeners: { 'exception': Testopia.Util.loadError },
totalProperty: 'totalResultsAvailable',
root: 'Result',
autoLoad: auto,
id: 'case_id',
fields: [{
name: "case_id",
mapping: "case_id"
}, {
name: "plan_id",
mapping: "plan_id"
}, {
name: "alias",
mapping: "alias"
}, {
name: "case_summary",
mapping: "summary"
}, {
name: "author",
mapping: "author_name"
}, {
name: "tester",
mapping: "default_tester"
}, {
name: "creation_date",
mapping: "creation_date"
}, {
name: "category",
mapping: "category_name"
}, {
name: "priority",
mapping: "priority"
}, {
name: "status",
mapping: "status"
}, {
name: "run_count",
mapping: "run_count"
}, {
name: "requirement",
mapping: "requirement"
}, {
name: "isautomated",
mapping: "isautomated"
}],
remoteSort: true
});
};
Ext.extend(Testopia.TestCase.Store, Ext.data.JsonStore);
Testopia.TestCase.StatusListStore = function(auto){
Testopia.TestCase.StatusListStore.superclass.constructor.call(this, {
url: 'tr_quicksearch.cgi',
root: 'statuses',
listeners: { 'exception': Testopia.Util.loadError },
baseParams: {
action: 'getcasestatus'
},
autoLoad: auto,
id: 'id',
fields: [{
name: 'id',
mapping: 'id'
}, {
name: 'name',
mapping: 'name'
}]
});
};
Ext.extend(Testopia.TestCase.StatusListStore, Ext.data.JsonStore);
Testopia.TestCase.ComponentStore = function(params, auto){
params.action = 'getcomponents';
Testopia.TestCase.ComponentStore.superclass.constructor.call(this, {
url: 'tr_quicksearch.cgi',
root: 'components',
baseParams: params,
listeners: { 'exception': Testopia.Util.loadError },
autoLoad: auto,
id: 'id',
fields: [{
name: 'id',
mapping: 'id'
}, {
name: 'name',
mapping: 'name'
}, {
name: 'qa',
mapping: 'qa_contact'
}, {
name: 'product',
mapping: 'product'
}]
});
};
Ext.extend(Testopia.TestCase.ComponentStore, Ext.data.JsonStore);
Testopia.TestCase.PriorityStore = function(auto){
Testopia.TestCase.PriorityStore.superclass.constructor.call(this, {
url: 'tr_quicksearch.cgi',
root: 'priorities',
listeners: { 'exception': Testopia.Util.loadError },
baseParams: {
action: 'getpriorities'
},
autoLoad: auto,
id: 'id',
fields: [{
name: 'id',
mapping: 'id'
}, {
name: 'name',
mapping: 'name'
}]
});
};
Ext.extend(Testopia.TestCase.PriorityStore, Ext.data.JsonStore);
Testopia.TestCase.StatusListCombo = function(cfg){
Testopia.TestCase.StatusListCombo.superclass.constructor.call(this, {
id: cfg.id || 'case_status_combo',
store: cfg.transform ? false : new Testopia.TestCase.StatusListStore(cfg.mode == 'local' ? true : false),
loadingText: 'Looking up statuses...',
displayField: 'name',
valueField: 'id',
typeAhead: true,
triggerAction: 'all',
minListWidth: 100,
forceSelection: true,
transform: cfg.transform,
emptyText: 'Please select...'
});
Ext.apply(this, cfg);
this.store.on('load', function(){
if (cfg.value) {
this.setValue(cfg.value);
}
}, this);
};
Ext.extend(Testopia.TestCase.StatusListCombo, Ext.form.ComboBox);
Testopia.TestCase.ComponentCombo = function(cfg){
Testopia.TestCase.ComponentCombo.superclass.constructor.call(this, {
id: cfg.id || 'component_combo',
store: cfg.transform ? false : new Testopia.TestCase.ComponentStore(cfg.params, cfg.mode == 'local' ? true : false),
loadingText: 'Looking up Components...',
displayField: 'name',
valueField: 'id',
editable: true,
triggerAction: 'all',
minListWidth: 300,
forceSelection: true,
transform: cfg.transform,
emptyText: 'Please select...'
});
Ext.apply(this, cfg);
this.store.on('load', function(){
if (cfg.value) {
this.setValue(cfg.value);
}
}, this);
};
Ext.extend(Testopia.TestCase.ComponentCombo, Ext.form.ComboBox);
Testopia.TestCase.PriorityCombo = function(cfg){
Testopia.TestCase.PriorityCombo.superclass.constructor.call(this, {
id: cfg.id || 'priority_combo',
store: cfg.transform ? false : new Testopia.TestCase.PriorityStore(cfg.mode == 'local' ? true : false),
loadingText: 'Looking up priorities...',
displayField: 'name',
valueField: 'id',
typeAhead: true,
triggerAction: 'all',
minListWidth: 100,
forceSelection: true,
transform: cfg.transform,
emptyText: 'Please select...'
});
Ext.apply(this, cfg);
this.store.on('load', function(){
if (cfg.value) {
this.setValue(cfg.value);
}
}, this);
};
Ext.extend(Testopia.TestCase.PriorityCombo, Ext.form.ComboBox);
Testopia.TestCase.Panel = function(params, cfg){
var cgrid = new Testopia.TestCase.Grid(params, cfg);
var filter = new Testopia.TestCase.Filter();
this.cgrid = cgrid;
this.store = cgrid.store;
this.params = params;
Testopia.TestCase.Panel.superclass.constructor.call(this, {
title: 'Test Cases',
layout: 'border',
id: 'case-panel',
items: [filter, cgrid]
});
this.on('activate', this.onActivate, this);
};
Ext.extend(Testopia.TestCase.Panel, Ext.Panel, {
onActivate: function(event){
if (!this.store.getCount()) {
this.store.load({
params: this.params
});
}
}
});
Testopia.TestCase.Filter = function(){
this.form = new Ext.form.BasicForm('testopia_helper_frm', {});
Testopia.TestCase.Filter.superclass.constructor.call(this, {
title: 'Search for Test Cases',
region: 'north',
layout: 'fit',
frame: true,
collapsible: true,
height: 120,
items: [{
buttons: [{
text: 'Search',
handler: function(){
Ext.getCmp('case_search').getForm().submit();
}
}]
}]
});
};
Ext.extend(Testopia.TestCase.Filter, Ext.Panel);
Testopia.TestCase.Grid = function(params, cfg){
params.limit = Ext.state.Manager.get('TESTOPIA_DEFAULT_PAGE_SIZE', 25);
params.current_tab = 'case';
this.params = params;
var categoryCombo = new Testopia.Category.Combo({
id: 'case_grid_cateogy_chooser',
hiddenName: 'category',
mode: 'remote',
params: {
product_id: params.product_id
},
listeners: {
'startedit': function(){
var pid = Ext.getCmp(cfg.id || 'case_grid').getSelectionModel().getSelected().get('product_id');
if (categoryCombo.store.baseParams.product_id != pid) {
categoryCombo.store.baseParams.product_id = pid;
categoryCombo.store.load();
}
}
}
});
this.store = new Ext.data.GroupingStore({
url: 'tr_list_cases.cgi',
baseParams: params,
reader: new Ext.data.JsonReader({
totalProperty: 'totalResultsAvailable',
root: 'Result',
id: 'case_id',
fields: [{
name: "case_id",
mapping: "case_id"
}, {
name: "sortkey",
mapping: "sortkey"
}, {
name: "plan_id",
mapping: "plan_id"
}, {
name: "alias",
mapping: "alias"
}, {
name: "summary",
mapping: "summary"
}, {
name: "author",
mapping: "author_name"
}, {
name: "tester",
mapping: "default_tester"
}, {
name: "creation_date",
mapping: "creation_date"
}, {
name: "category",
mapping: "category_name"
}, {
name: "priority",
mapping: "priority"
}, {
name: "status",
mapping: "status"
}, {
name: "run_count",
mapping: "run_count"
}, {
name: "requirement",
mapping: "requirement"
}, {
name: "product_id",
mapping: "product_id"
}, {
name: "component",
mapping: "component"
}, {
name: "modified",
mapping: "modified"
}, {
name: "isautomated",
mapping: "isautomated"
}, {
name: "plan_name",
mapping: "plan_name"
}, {
name: "average_time",
mapping: "average_time"
}, {
name: "estimated_time",
mapping: "estimated_time"
}]
}),
listeners: { 'exception': Testopia.Util.loadError },
remoteSort: true,
sortInfo: {
field: 'case_id',
direction: "ASC"
},
groupField: params.plan_id ? '' : 'plan_id'
});
var ds = this.store;
ds.paramNames.sort = "order";
ds.on('beforeload', function(store, o){
store.baseParams.ctype = 'json';
});
this.columns = [{
header: "ID",
width: 50,
dataIndex: 'case_id',
sortable: true,
groupRenderer: function(v){
return v;
},
renderer: Testopia.Util.makeLink.createDelegate(this,['case'],true),
hideable: false
}, {
header: "Sort Key",
width: 50,
sortable: true,
dataIndex: 'sortkey',
editor: {
xtype: 'numberfield',
allowBlank: true,
allowDecimals: false,
allowNegative: false
},
id: "sortkey"
}, {
header: "Summary",
width: 220,
dataIndex: 'summary',
id: "case_summary",
sortable: true,
editor: {
xtype: 'textfield',
allowBlank: false
}
}, {
header: "Author",
width: 150,
sortable: true,
dataIndex: 'author',
hidden: true
}, {
header: "Default Tester",
width: 150,
sortable: true,
dataIndex: 'tester',
editor: new Testopia.User.Lookup({
hiddenName: 'tester'
}),
renderer: Testopia.Util.ComboRenderer.createDelegate(this)
}, {
header: "Created",
width: 110,
sortable: true,
dataIndex: 'creation_date',
hidden: true
}, {
header: "Last Modified",
width: 110,
sortable: true,
dataIndex: 'modified',
hidden: true
}, {
header: "Priority",
width: 100,
sortable: true,
dataIndex: 'priority',
editor: new Testopia.TestCase.PriorityCombo({
hiddenName: 'priority',
mode: 'remote'
}),
renderer: Testopia.Util.ComboRenderer.createDelegate(this)
}, {
header: "Category",
width: 100,
sortable: true,
dataIndex: 'category',
editor: categoryCombo,
renderer: Testopia.Util.ComboRenderer.createDelegate(this)
}, {
header: "Component",
width: 110,
sortable: true,
dataIndex: 'component'
}, {
header: "Status",
width: 100,
sortable: true,
dataIndex: 'status',
editor: new Testopia.TestCase.StatusListCombo('status'),
renderer: Testopia.Util.ComboRenderer.createDelegate(this)
}, {
header: "Requirement",
width: 40,
sortable: true,
dataIndex: 'requirement',
hidden: true,
editor: {
xtype: 'textfield',
name: 'requirement'
}
}, {
header: "Estimated Time",
width: 60,
sortable: true,
dataIndex: 'estimated_time',
editor: {
xtype: 'textfield'
},
hidden: true
}, {
header: "Average Time",
width: 60,
sortable: false,
dataIndex: 'average_time',
hidden: true
}, {
header: "Plan",
width: 40,
sortable: true,
dataIndex: 'plan_id',
hidden: true,
renderer: Testopia.Util.makeLink.createDelegate(this,['plan'],true),
groupRenderer: function(v, u, r){
return v + ': "' + r.get('plan_name') + '"';
}
}, {
header: "Run Count",
width: 40,
sortable: false,
dataIndex: 'run_count',
hidden: true
}];
this.view = new Ext.grid.GroupingView({
forceFit: true,
groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Items" : "Item"]})'
});
this.form = new Ext.form.BasicForm('testopia_helper_frm', {});
this.bbar = new Testopia.Util.PagingBar('case', this.store);
Testopia.TestCase.Grid.superclass.constructor.call(this, {
title: 'Test Cases',
id: cfg.id || 'case_grid',
loadMask: {
msg: 'Loading Test Cases...'
},
layout: 'fit',
stripeRows: true,
region: 'center',
autoExpandColumn: "case_summary",
autoScroll: true,
plugins: [new Ext.ux.grid.RowEditor({
id:'case_row_editor',
saveText: 'Update'
})],
sm: new Ext.grid.RowSelectionModel({
singleSelect: false,
listeners: {
'rowselect': function(sm, i, r){
if (Ext.getCmp('delete_case_list_btn')) {
Ext.getCmp('delete_case_list_btn').enable();
Ext.getCmp('edit_case_list_btn').enable();
}
},
'rowdeselect': function(sm, i, r){
if (sm.getCount() < 1) {
if (Ext.getCmp('delete_case_list_btn')) {
Ext.getCmp('delete_case_list_btn').disable();
Ext.getCmp('edit_case_list_btn').disable();
}
}
}
}
}),
viewConfig: {
forceFit: true
},
tbar: [new Ext.Toolbar.Fill(), 
{
xtype: 'button',
id: 'case_grid_tocsv',
icon: 'extensions/testopia/img/csv.png',
iconCls: 'img_button_16x',
tooltip: 'Export Test Cases to CSV',
handler: function(){
window.location = 'tr_list_cases.cgi?ctype=csv&viewall=1&' + Testopia.Util.JSONToURLQuery(Ext.getCmp(cfg.id || 'case_grid').store.baseParams, '', ['viewall', 'ctype']);
}
},{
xtype: 'button',
id: 'case_grid_toxml',
icon: 'extensions/testopia/img/xml.png',
iconCls: 'img_button_16x',
tooltip: 'Export Test Cases to XML',
handler: function(){
window.location = 'tr_list_cases.cgi?ctype=xml&viewall=1&' + Testopia.Util.JSONToURLQuery(Ext.getCmp(cfg.id || 'case_grid').store.baseParams, '', ['viewall', 'ctype']);
}
},{
xtype: 'button',
id: 'save_case_list_btn',
icon: 'extensions/testopia/img/save.png',
iconCls: 'img_button_16x',
tooltip: 'Save this search',
handler: function(b, e){
Testopia.Search.save('case', Ext.getCmp(cfg.id || 'case_grid').store.baseParams);
}
}, {
xtype: 'button',
id: 'link_case_list_btn',
icon: 'extensions/testopia/img/link.png',
iconCls: 'img_button_16x',
tooltip: 'Create a link to this list',
handler: function(b, e){
Testopia.Search.LinkPopup(Ext.getCmp(cfg.id || 'case_grid').store.baseParams);
}
}, {
xtype: 'button',
id: 'edit_case_list_btn',
icon: 'extensions/testopia/img/edit.png',
disabled: true,
iconCls: 'img_button_16x',
tooltip: 'Edit Selected Test Case',
handler: function(){
Testopia.Util.editFirstSelection(Ext.getCmp(cfg.id || 'case_grid'));
}
}, {
xtype: 'button',
id: 'add_case_list_btn',
icon: 'extensions/testopia/img/new.png',
iconCls: 'img_button_16x',
tooltip: 'Create a New Test Case',
handler: function(){
try {
if (plan) {
Testopia.TestCase.NewCasePopup(plan.plan_id, plan.product_id);
}
} 
catch (err) {
window.location = 'tr_new_case.cgi';
}
}
}, {
xtype: 'button',
id: 'delete_case_list_btn',
disabled: true,
icon: 'extensions/testopia/img/delete.png',
iconCls: 'img_button_16x',
tooltip: 'Delete Selected Test Cases',
handler: this.deleteList.createDelegate(this)
}]
});
Ext.apply(this, cfg);
this.on('activate', this.onActivate, this);
this.on('rowcontextmenu', this.onContextClick, this);
Ext.getCmp('case_row_editor').on('afteredit', this.onGridEdit, this);
};
Ext.extend(Testopia.TestCase.Grid, Ext.grid.GridPanel, {
onContextClick: function(grid, index, e){
grid.selindex = index;
if (!this.menu) { // create context menu on first right click
var hasplan;
try {
hasplan = plan ? false : true;
} 
catch (err) {
hasplan = true;
}
this.menu = new Ext.menu.Menu({
id: 'case_list_ctx_menu',
enableScrolling: false,
items: [{
text: 'Modify Selected Test Cases',
icon: 'extensions/testopia/img/edit.png',
iconCls: 'img_button_16x',
menu: {
enableScrolling: false,
items: [{
text: 'Requirements',
handler: function(){
Ext.Msg.prompt('Edit Requirements', '', function(btn, text){
if (btn == 'ok') {
Testopia.Util.updateFromList('case', {
requirement: text,
ids: Testopia.Util.getSelectedObjects(grid, 'case_id')
}, grid);
}
});
}
}, {
text: 'Category',
disabled: hasplan,
handler: function(){
var win = new Ext.Window({
title: 'Edit Category',
id: 'status-win',
plain: true,
shadow: false,
width: 300,
height: 150,
items: [new Testopia.Category.Combo({
fieldLabel: 'Category',
params: {
product_id: plan.product_id
}
})],
buttons: [{
text: 'Submit',
handler: function(){
Testopia.Util.updateFromList('case', {
category: Ext.getCmp('case_category_combo').getValue(),
ids: Testopia.Util.getSelectedObjects(grid, 'case_id')
}, grid);
win.close();
}
}, {
text: 'Close',
handler: function(){
win.close();
}
}]
});
win.show(this);
}
}, {
text: 'Status',
handler: function(){
var win = new Ext.Window({
title: 'Edit Status',
id: 'status-win',
plain: true,
shadow: false,
listeners: {'afterlayout':function(){Ext.getCmp('case_status_update').focus('',10)}},
width: 300,
height: 150,
items: [new Testopia.TestCase.StatusListCombo({
id:'case_status_update',
fieldLabel: 'Status'
})],
buttons: [{
text: 'Submit',
handler: function(){
Testopia.Util.updateFromList('case', {
status: Ext.getCmp('case_status_combo').getValue(),
ids: Testopia.Util.getSelectedObjects(grid, 'case_id')
}, grid);
win.close();
}
}, {
text: 'Close',
handler: function(){
win.close();
}
}]
});
win.show(this);
}
}, {
text: 'Priority',
handler: function(){
var win = new Ext.Window({
title: 'Edit Priority',
id: 'priority-win',
layout: 'form',
plain: true,
shadow: false,
listeners: {'afterlayout':function(){Ext.getCmp('case_priority_update').focus('',10)}},
width: 300,
height: 150,
labelWidth: 30,
items: [new Testopia.TestCase.PriorityCombo({
id: 'case_priority_update',
fieldLabel: 'Priority'
})],
buttons: [{
text: 'Submit',
handler: function(){
Testopia.Util.updateFromList('case', {
priority: Ext.getCmp('case_priority_update').getValue(),
ids: Testopia.Util.getSelectedObjects(grid, 'case_id')
}, grid);
win.close();
}
}, {
text: 'Close',
handler: function(){
win.close();
}
}]
});
win.show(this);
}
}, {
text: 'Tester',
handler: function(){
var win = new Ext.Window({
title: 'Change Default Tester',
id: 'def_tester_win',
layout: 'fit',
plain: true,
shadow: false,
split: true,
listeners: {'afterlayout':function(){Ext.getCmp('tester_update').focus('',10)}},
width: 350,
height: 150,
items: [new Ext.FormPanel({
labelWidth: '40',
bodyStyle: 'padding: 5px',
items: [new Testopia.User.Lookup({
id: 'tester_update',
fieldLabel: 'Default Tester'
})]
})],
buttons: [{
text: 'Update Tester',
handler: function(){
Testopia.Util.updateFromList('case', {
tester: Ext.getCmp('tester_update').getValue(),
ids: Testopia.Util.getSelectedObjects(grid, 'case_id')
}, grid);
win.close();
}
}, {
text: 'Cancel',
handler: function(){
win.close();
}
}]
});
win.show();
}
}, {
text: 'Automation',
handler: function(){
var chbx = new Ext.form.Checkbox({
checked: false,
name: 'isautomated',
id: 'isautomated_update',
fieldLabel: 'Enable Automation'
});
var scripttext = new Ext.form.TextField({
xtype: 'textfield',
disabled: true,
name: 'script',
fieldLabel: 'Script '
});
var argumenttext = new Ext.form.TextField({
xtype: 'textfield',
name: 'arguments',
disabled: true,
fieldLabel: 'Arguments '
});
chbx.on('check', function(){
if (scripttext.disabled) {
scripttext.enable();
argumenttext.enable();
}
else {
scripttext.disable();
argumenttext.disable();
}
}, chbx);
var win = new Ext.Window({
title: 'Edit Automation Settings',
id: 'auto-win',
layout: 'form',
plain: true,
shadow: false,
listeners: {'afterlayout':function(){Ext.getCmp('isautomated_update').focus('',10)}},
width: 350,
height: 250,
items: [{
id: 'automation_form',
bodyStyle: 'padding: 5px',
xtype: 'form',
items: [chbx, argumenttext, scripttext]
}],
buttons: [{
text: 'Submit',
handler: function(){
params = Ext.getCmp('automation_form').getForm().getValues();
params.ids = Testopia.Util.getSelectedObjects(grid, 'case_id');
Testopia.Util.updateFromList('case', params, grid);
win.close();
}
}, {
text: 'Close',
handler: function(){
win.close();
}
}]
});
win.show(this);
}
}]
}
}, {
text: 'Delete Selected Test Cases',
icon: 'extensions/testopia/img/delete.png',
iconCls: 'img_button_16x',
handler: this.deleteList.createDelegate(this)
}, {
text: 'Add Selected Test Cases to Run... ',
handler: function(){
Ext.Msg.prompt('Add to runs', '', function(btn, text){
if (btn == 'ok') {
Testopia.Util.updateFromList('case', {
addruns: text,
ids: Testopia.Util.getSelectedObjects(grid, 'case_id')
}, grid);
}
});
}
}, {
text: 'Copy or Link Selected Test Cases to Plan(s)... ',
handler: function(){
var r = grid.getSelectionModel().getSelected();
Testopia.TestCase.clonePopup(r.get('product_id'), Testopia.Util.getSelectedObjects(grid, 'case_id'));
}
}, {
text: 'Unlink from Plan',
disabled: hasplan,
handler: function(){
Ext.Msg.show({
title: 'Unlink Selected Test Cases',
msg: 'You are about to unlink the selected test cases from this plan. If a test case is not linked to any other plans, it will be deleted. Do you want to continue?',
buttons: Ext.Msg.YESNO,
icon: Ext.Msg.WARNING,
fn: function(btn){
if (btn == 'yes') {
var testopia_form = new Ext.form.BasicForm('testopia_helper_frm');
testopia_form.submit({
url: 'tr_list_cases.cgi',
params: {
case_ids: Testopia.Util.getSelectedObjects(grid, 'case_id'),
action: 'unlink',
plan_id: plan.plan_id
},
success: function(data){
Ext.Msg.show({
msg: "Test cases removed",
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.INFO
});
grid.store.reload();
},
failure: function(f, a){
Testopia.Util.error(f, a);
grid.store.reload();
}
});
}
}
})
}
}, {
text: 'Add or Remove Tags from Selected Cases...',
handler: function(){
Testopia.Tags.update('case', grid);
}
}, {
text: 'Add or Remove Bugs from Selected Cases...',
handler: function(){
Testopia.TestCase.Bugs.update(grid);
}
}, {
text: 'Add or Remove Components from Selected Cases...',
handler: function(){
var win = new Ext.Window({
title: 'Add or Remove Components',
id: 'component_update_win',
layout: 'fit',
split: true,
plain: true,
shadow: false,
width: 550,
height: 85,
items: [new Testopia.TestCase.Components(grid)]
});
win.show();
}
}, {
text: 'Refresh List',
icon: 'extensions/testopia/img/refresh.png',
iconCls: 'img_button_16x',
handler: function(){
grid.store.reload();
}
}, {
text: 'View Test Case(s) in a New Tab',
handler: function(){
var case_ids = Testopia.Util.getSelectedObjects(grid, 'case_id').split(',');
var i;
for (i = 0; i < case_ids.length; i += 1) {
window.open('tr_show_case.cgi?case_id=' + case_ids[i]);
}
}
}]
});
}
e.stopEvent();
if (grid.getSelectionModel().getCount() < 1) {
grid.getSelectionModel().selectRow(index);
}
this.menu.showAt(e.getXY());
},
onGridEdit: function(e){
var ds = this.store;
var myparams = e.record.data;
myparams.action = 'edit';
var tester;
if (!myparams.tester.match('@')){
tester = myparams.tester;
delete myparams.tester;
}
this.form.submit({
url: "tr_process_case.cgi",
params: myparams,
success: function(f, a){
if (tester)
myparams.tester = tester;
ds.commitChanges();
},
failure: function(f, a){
Testopia.Util.error(f, a);
if (tester)
myparams.tester = tester;
ds.rejectChanges();
}
});
},
deleteList: function(){
var grid = this;
Ext.Msg.show({
title: 'Confirm Delete?',
msg: CASE_DELETE_WARNING,
buttons: Ext.Msg.YESNO,
animEl: 'case-delete-btn',
icon: Ext.MessageBox.QUESTION,
fn: function(btn){
if (btn == 'yes') {
var testopia_form = new Ext.form.BasicForm('testopia_helper_frm');
testopia_form.submit({
url: 'tr_list_cases.cgi',
params: {
case_ids: Testopia.Util.getSelectedObjects(grid, 'case_id'),
action: 'delete'
},
success: function(data){
Ext.Msg.show({
msg: "Test cases deleted",
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.INFO
});
grid.store.reload();
},
failure: function(f, a){
Testopia.Util.error(f, a);
grid.store.reload();
}
});
}
}
});
},
onActivate: function(event){
if (!this.store.getCount()) {
this.store.load();
}
}
});
Testopia.TestCase.NewCaseForm = function(plan_ids, product_id, run_id){
Testopia.TestCase.NewCaseForm.superclass.constructor.call(this, {
id: 'newcaseform',
url: 'tr_new_case.cgi',
baseParams: {
action: 'add'
},
fileUpload: true,
labelAlign: 'left',
frame: true,
title: 'Create a New Test Case',
bodyStyle: 'padding:5px 5px 0',
width: 1050,
height: 514,
items: [{
layout: 'table',
layoutConfig: {
columns: 2,
width: '100%'
},
items: [{
colspan: 2,
layout: 'form',
items: [{
id: 'ncf-summary',
xtype: 'textfield',
fieldLabel: '<b>Summary</b>',
name: 'summary',
allowBlank: false,
width: 800
}, {
xtype: 'hidden',
name: 'components',
id: 'compfield'
}, {
xtype: 'hidden',
name: 'plan_id',
id: 'planfield',
value: plan_ids
}]
}, {
layout: 'form',
items: [new Testopia.User.Lookup({
id: 'default_tester',
hiddenName: 'tester',
fieldLabel: 'Default Tester'
}), {
xtype: 'textfield',
fieldLabel: 'Alias',
id: 'case_alias',
name: 'alias'
}, new Testopia.TestCase.PriorityCombo({
fieldLabel: '<b>Priority</b>&nbsp;&nbsp;<img src="images/help.png" id="priority_help" style="cursor:pointer" onclick=\'window.open("testing_priorities.html","Priority Definitions","resizable=no, scrollbars=yes, width=550,height=420");\'/>',
hiddenName: 'priority',
mode: 'local',
allowBlank: false
}), new Testopia.Category.Combo({
fieldLabel: '<b>Category</b>',
hiddenName: 'category',
mode: 'local',
allowBlank: false,
params: {
product_id: product_id
}
}), {
xtype: 'textfield',
fieldLabel: 'Estimated Time (HH:MM:SS)',
id: 'estimated_time',
name: 'estimated_time'
}, {
xtype: 'textfield',
fieldLabel: 'Bugs',
id: 'ncf-bugs',
name: 'bugs'
}, {
xtype: 'textfield',
fieldLabel: 'Blocks',
id: 'ncf-blocks',
name: 'tcblocks'
}]
}, {
layout: 'form',
items: [new Testopia.TestCase.StatusListCombo({
fieldLabel: '<b>Status</b>',
hiddenName: 'status',
mode: 'local',
value: DEFAULT_CASE_STATUS,
allowBlank: false,
id: 'ncf-casestatus'
}), {
xtype: 'textfield',
fieldLabel: 'Add Tags',
id: 'ncf-addtags',
name: 'addtags'
}, {
xtype: 'textfield',
fieldLabel: 'Requirements',
id: 'ncf-reqs',
name: 'requirement'
}, {
xtype: 'checkbox',
fieldLabel: 'Automated',
id: 'ncf-automated',
name: 'isautomated',
value: '1'
}, {
xtype: 'textfield',
fieldLabel: 'Scripts',
id: 'ncf-scripts',
name: 'script'
}, {
xtype: 'textfield',
fieldLabel: 'Arguments',
id: 'ncf-arguments',
name: 'arguments'
}, {
xtype: 'textfield',
fieldLabel: 'Add to Run',
id: 'ncf-addtorun',
name: 'addruns',
value: run_id
}, {
xtype: 'textfield',
fieldLabel: 'Depends On',
id: 'ncf-dependson',
name: 'tcdependson'
}]
}]
}, {
xtype: 'tabpanel',
id: 'ncf_tabs',
height: 200,
activeItem: 0,
items:[{
layout: 'anchor',
title: 'Description',
id: 'ncf_action_panel',
items: [{
xtype: 'checkbox',
id: 'ncf-usefromwiki',
name: 'tcusefromwiki',
boxLabel: 'Use from Wiki',
checked: true,
value: 1,
listeners: {
check: function(h, t) {
document.getElementById('ncf_action_effect_editors').style.display = t ? 'none' : '';
Ext.getCmp('ncf_action_panel').doLayout();
if (t)
document.getElementById('ncf-action-field').value = '';
else
document.getElementById('ncf-action-field').value = Ext.getCmp('ncf-action').value;
},
},
},{
layout: 'column',
id: 'ncf_action_effect_editors',
style: { display: 'none' },
items: [{
columnWidth: 0.5,
id: 'ncf_action_editor_col',
items:[{
title: 'Action',
layout: 'fit',
items: [{
id: 'ncf-action',
xtype:'htmleditor',
scrollable:true,
listeners:{'initialize':function(h){
if (!h.getValue()) {
var httpRequest = new Ext.data.Connection();
httpRequest.request({
url: 'tr_quicksearch.cgi',
params: {
action: 'get_action'
},
success: function(d){
h.setValue(d.responseText);
},
failure: testopiaError
});
}
},
'change':function(h){
if (!h._hid)
h._hid = document.getElementById('ncf-action-field');
h._hid.value = h.value;
}}
},{
tag:   'input',
type:  'hidden',
name:  'tcaction',
value: '',
id:    'ncf-action-field',
}]
}]
},{
columnWidth: 0.5,
id: 'ncf_effect_editor_col',
items:[{
title: 'Expected Results',
layout: 'fit',
items: [{
id: 'ncf-effect',
name: 'tceffect',
xtype:'htmleditor',
scrollable:true,
listeners:{'initialize':function(h){
if(!h.getValue()){
var httpRequest = new Ext.data.Connection();
httpRequest.request({
url: 'tr_quicksearch.cgi',
params:{
action: 'get_effect'
}, 
success:function(d){
h.setValue(d.responseText);
}, 
failure: testopiaError
});      
}
}}
}]
}]
}]
}]
}, new Testopia.Attachment.Form(), {
title: 'Components',
id: 'component_picker',
height: 200,
layout: 'fit',
xtype: 'grid',
store: new Testopia.TestCase.ComponentStore({
product_id: product_id
}, true),
columns: [{
sortable: true,
dataIndex: 'name',
width: 500
}],
sm: new Ext.grid.RowSelectionModel({
singleSelect: false
}),
tbar: ['Product', ' ', new Testopia.Product.Combo({
mode: 'local',
value: product_id,
id: 'comp_product_combo'
})]
}]
}],
buttons: [{
text: 'Submit',
handler: function(){
if (!Ext.getCmp('newcaseform').getForm().isValid()) {
return;
}
Ext.getCmp('newcaseform').getForm().submit({
method: 'POST',
success: function(form, data){
if (data.result.err) {
alert('One or more attachments were either too large or were empty. These have been ignored.');
}
Ext.Msg.show({
title: 'Test Case Created',
msg: 'Test case ' + data.result.tc + ' Created. Would you like to go there now?',
buttons: Ext.Msg.YESNO,
icon: Ext.MessageBox.QUESTION,
fn: function(btn){
if (btn == 'yes') {
window.location = 'tr_show_case.cgi?case_id=' + data.result.tc;
}
}
});
if (Ext.getCmp('plan_case_grid')) {
Ext.getCmp('plan_case_grid').store.reload();
}
else 
if (Ext.getCmp('newrun_casegrid')) {
Ext.getCmp('newrun_casegrid').store.reload();
}
else 
if (Ext.getCmp('caserun_grid')) {
Ext.getCmp('caserun_grid').store.reload();
}
else 
if (Ext.getCmp('product_case_grid')) {
Ext.getCmp('product_case_grid').store.reload();
}
},
failure: Testopia.Util.error
});
}
}, {
text: 'Cancel',
id: 'ncf_cancel_btn',
handler: function(){
Ext.getCmp('newcaseform').getForm().reset();
try {
if (Ext.getCmp('newcase-win')) {
Ext.getCmp('newcase-win').close();
}
else {
window.location = 'tr_show_product.cgi';
}
} 
catch (err) {
}
}
}]
});
if (Param_Show_Setup_Breakdown)
{
Ext.getCmp('ncf_tabs').insert(0, new Ext.Panel({
layout: 'column',
title: 'Setup Procedures',
items: [{
columnWidth: 0.5,
items:[{
title: 'Setup',
layout: 'fit',
items: [{
id: 'ncf-setup_doc',
name: 'tcsetup',
xtype:'htmleditor',
scrollable:true
}]
}]
},{
columnWidth: 0.5,
items:[{
title: 'Break Down',
layout: 'fit',
items: [{
id: 'ncf-breakdown_doc',
name: 'tcbreakdown',
xtype:'htmleditor',
scrollable:true
}]
}]
}]
}));
Ext.getCmp('ncf_tabs').doLayout();
}
Ext.getCmp('comp_product_combo').on('select', function(c,r,i){
Ext.getCmp('component_picker').store.baseParams.product_id = r.get('id');
Ext.getCmp('component_picker').store.load();
});
Ext.getCmp('component_picker').getSelectionModel().on('rowselect', function(m, i, r){
Ext.getCmp('compfield').setValue(Testopia.Util.getSelectedObjects(Ext.getCmp('component_picker'), 'id'));
Ext.getCmp('default_tester').setValue(r.get('qa'));
});
Ext.getCmp('ncf_tabs').on('tabchange', function(t, p){
p.doLayout();
});
};
Ext.extend(Testopia.TestCase.NewCaseForm, Ext.form.FormPanel);
Testopia.TestCase.NewCasePopup = function(plans, product_id, run_id){
var win = new Ext.Window({
id: 'newcase-win',
closable: true,
width: Ext.getBody().getViewSize().width - 150,
height: Ext.getBody().getViewSize().height - 150,
plain: true,
shadow: false,
layout: 'fit',
items: [new Testopia.TestCase.NewCaseForm(plans, product_id, run_id)]
});
win.show(this);
};
Testopia.TestCase.PlanList = function(tcid, product_id){
this.remove = function(){
var form = new Ext.form.BasicForm('testopia_helper_frm', {});
form.submit({
url: 'tr_process_case.cgi',
params: {
action: 'unlink',
plan_id: Testopia.Util.getSelectedObjects(Ext.getCmp('case_plan_grid'), 'plan_id'),
case_id: tcid
},
success: function(){
ds.load();
},
failure: Testopia.Util.error
});
};
this.store = new Ext.data.JsonStore({
url: 'tr_process_case.cgi',
listeners: { 'exception': Testopia.Util.loadError },
baseParams: {
action: 'getplans',
case_id: tcid
},
root: 'plans',
id: 'plan_id',
fields: [{
name: 'plan_id',
mapping: 'plan_id'
}, {
name: 'plan_name',
mapping: 'plan_name'
}]
});
var ds = this.store;
this.columns = [{
header: 'ID',
dataIndex: 'plan_id',
hideable: false,
renderer: Testopia.Util.makeLink.createDelegate(this,['plan'],true)
}, {
header: 'Name',
width: 150,
dataIndex: 'plan_name',
id: 'plan_name',
sortable: true,
hideable: false
}];
var newplan = new Ext.form.ComboBox({
store: new Testopia.TestPlan.Store({
product_id: product_id,
viewall: 1
}, false),
loadingText: 'Looking up plans...',
id: 'link_plan_combo',
width: 150,
displayField: 'name',
valueField: 'plan_id',
typeAhead: true,
triggerAction: 'all',
minListWidth: 300,
forceSelection: true,
emptyText: 'Choose a Plan...'
});
var addButton = new Ext.Button({
icon: 'extensions/testopia/img/add.png',
iconCls: 'img_button_16x',
tooltip: 'Link to plan',
handler: function(){
var form = new Ext.form.BasicForm('testopia_helper_frm', {});
form.submit({
url: 'tr_process_case.cgi',
params: {
action: 'link',
plan_ids: newplan.getValue(),
case_id: tcid
},
success: function(){
ds.load();
},
failure: Testopia.Util.error
});
}
});
var deleteButton = new Ext.Button({
icon: 'extensions/testopia/img/delete.png',
iconCls: 'img_button_16x',
tooltip: 'Unlink Selected Plans',
handler: this.remove
});
Testopia.TestCase.PlanList.superclass.constructor.call(this, {
title: 'Plans',
split: true,
layout: 'fit',
autoExpandColumn: "plan_name",
collapsible: true,
id: 'case_plan_grid',
loadMask: {
msg: 'Loading plans...'
},
autoScroll: true,
sm: new Ext.grid.RowSelectionModel({
singleSelect: true
}),
viewConfig: {
forceFit: true
},
tbar: [newplan, addButton, deleteButton]
});
ds.on('load', function(s, r, o){
if (s.getCount() == 1) {
deleteButton.disable();
}
else {
deleteButton.enable();
}
});
this.on('rowcontextmenu', this.onContextClick, this);
this.on('activate', this.onActivate, this);
};
Ext.extend(Testopia.TestCase.PlanList, Ext.grid.GridPanel, {
onContextClick: function(grid, index, e){
grid.getSelectionModel().selectRow(index);
if (!this.menu) { // create context menu on first right click
this.menu = new Ext.menu.Menu({
id: 'tags-ctx-menu',
items: [{
text: 'Unlink Selected Plans',
id: 'plan_remove_mnu',
icon: 'extensions/testopia/img/delete.png',
iconCls: 'img_button_16x',
handler: grid.remove
}, {
text: 'Go to Plan',
handler: function(){
window.location = 'tr_show_plan.cgi?plan_id=' + grid.getSelectionModel().getSelected().get('plan_id');
}
}, {
text: 'Refresh',
icon: 'extensions/testopia/img/refresh.png',
iconCls: 'img_button_16x',
handler: function(){
grid.store.reload();
}
}]
});
}
if (this.store.getCount() == 1) {
Ext.getCmp('plan_remove_mnu').disable();
}
else {
Ext.getCmp('plan_remove_mnu').enable();
}
e.stopEvent();
this.menu.showAt(e.getXY());
},
onActivate: function(event){
if (!this.store.getCount()) {
this.store.load();
}
}
});
Testopia.TestCase.Clone = function(product_id, cases){
var pgrid = new Testopia.TestPlan.Grid({
product_id: product_id
}, {
id: 'plan_clone_grid'
});
Testopia.TestCase.Clone.superclass.constructor.call(this, {
id: 'case-clone-panel',
layout: 'border',
items: [{
region: 'north',
layout: 'fit',
border: false,
height: 300,
items: [pgrid]
}, {
region: 'center',
xtype: 'form',
title: 'Clone Options',
id: 'case_clone_frm',
border: false,
frame: true,
autoScroll: true,
bodyStyle: 'padding: 10px',
labelWidth: 250,
height: 280,
items: [{
xtype: 'fieldset',
autoHeight: true,
checkboxToggle: true,
checkboxName: 'copy_cases',
title: 'Create a copy (Unchecking will create a link to selected plans)',
id: 'case_copy_method',
collapsed: true,
items: [{
xtype: 'hidden',
id: 'case_copy_plan_ids',
name: 'plan_ids'
}, {
xtype: 'hidden',
id: 'case_clone_product_id',
value: product_id,
name: 'product_id'
}, {
xtype: 'checkbox',
boxLabel: 'Keep Author (unchecking will make you the author of copied cases)',
hideLabel: true,
name: 'keep_author',
checked: true
}, {
xtype: 'checkbox',
boxLabel: 'Keep Default Tester (unchecking will make you the default tester of copied cases)',
hideLabel: true,
name: 'keep_tester',
checked: true
}, {
xtype: 'checkbox',
boxLabel: 'Copy case document (action, expected results, etc.)',
hideLabel: true,
name: 'copy_doc',
checked: true
}, {
xtype: 'checkbox',
boxLabel: 'Copy Attachments',
hideLabel: true,
name: 'copy_attachments'
}, {
xtype: 'checkbox',
boxLabel: 'Copy Tags',
hideLabel: true,
name: 'copy_tags',
checked: true
}, {
xtype: 'checkbox',
boxLabel: 'Copy components',
hideLabel: true,
name: 'copy_comps',
checked: true
}, {
xtype: 'checkbox',
boxLabel: 'Copy category to new product',
hideLabel: true,
disabled: true,
id: 'case_clone_category_box',
name: 'copy_category',
checked: true
}]
}]
}],
buttons: [{
text: 'Submit',
handler: function(){
Ext.getCmp('case_copy_plan_ids').setValue(Testopia.Util.getSelectedObjects(Ext.getCmp('plan_clone_grid'), 'plan_id'));
var form = Ext.getCmp('case_clone_frm').getForm();
var params = form.getValues();
form.baseParams = {};
form.baseParams.action = 'clone';
form.baseParams.ids = cases;
form.submit({
url: 'tr_list_cases.cgi',
success: function(form, data){
if (params.copy_cases) {
if (data.result.tclist.length == 1) {
Ext.Msg.show({
title: 'Test Case Copied',
msg: 'Test case ' + data.result.tclist[0] + ' Copied from Case ' + cases + '. Would you like to go there now?',
buttons: Ext.Msg.YESNO,
icon: Ext.MessageBox.QUESTION,
fn: function(btn){
if (btn == 'yes') {
window.location = 'tr_show_case.cgi?case_id=' + data.result.tclist[0];
}
}
});
}
else {
Ext.Msg.show({
title: 'Test Case Copied',
msg: data.result.tclist.length + ' Test cases Copied successfully <a href="tr_list_cases.cgi?case_id=' + data.result.tclist.join(',') + '">View List</a>',
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.INFO
});
}
}
else {
Ext.Msg.show({
title: 'Test Case(s) Linked',
msg: 'Test cases ' + cases + ' Linked successfully',
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.INFO
});
}
Ext.getCmp('case-clone-win').close();
try {
Ext.getCmp('case_plan_grid').store.reload();
} 
catch (err) {
};
},
failure: Testopia.Util.error
});
}
}, {
text: 'Cancel',
handler: function(){
try {
Ext.getCmp('case-clone-win').close();
} 
catch (err) {
window.location = 'tr_show_product.cgi';
}
}
}]
});
};
Ext.extend(Testopia.TestCase.Clone, Ext.Panel);
Testopia.TestCase.clonePopup = function(product_id, cases){
var win = new Ext.Window({
id: 'case-clone-win',
closable: true,
width: 800,
height: 550,
plain: true,
shadow: false,
layout: 'fit',
items: [new Testopia.TestCase.Clone(product_id, cases)]
});
var pg = Ext.getCmp('plan_clone_grid');
Ext.apply(pg, {
title: 'Select plans to clone cases to'
});
win.show(this);
var pchooser = new Testopia.Product.Combo({
id: 'case_clone_win_product_chooser',
mode: 'local',
value: product_id
});
pchooser.on('select', function(c, r, i){
pg.store.baseParams = {
ctype: 'json',
product_id: r.get('id')
};
if (r.get('id') != product_id) {
Ext.getCmp('case_clone_category_box').enable();
}
else {
Ext.getCmp('case_clone_category_box').disable();
}
Ext.getCmp('case_clone_product_id').setValue(r.get('id'));
pg.store.load();
});
pg.getTopToolbar().removeAll();
pg.getTopToolbar().add('Product: ', pchooser);
pg.getSelectionModel().un('rowselect', pg.getSelectionModel().events['rowselect'].listeners[0].fn);
pg.getSelectionModel().un('rowdeselect', pg.getSelectionModel().events['rowdeselect'].listeners[0].fn);
pg.store.load();
};
Testopia.TestCaseRun.StatusListStore = function(auto){
Testopia.TestCaseRun.StatusListStore.superclass.constructor.call(this, {
url: 'tr_quicksearch.cgi',
root: 'statuses',
listeners: { 'exception': Testopia.Util.loadError },
baseParams: {
action: 'getcaserunstatus'
},
autoLoad: auto,
id: 'id',
fields: [{
name: 'id',
mapping: 'id'
}, {
name: 'name',
mapping: 'name'
}]
});
};
Ext.extend(Testopia.TestCaseRun.StatusListStore, Ext.data.JsonStore);
Testopia.TestCaseRun.StatusListCombo = function(cfg){
Testopia.TestCaseRun.StatusListCombo.superclass.constructor.call(this, {
id: cfg.id || 'case_run_status_combo',
store: cfg.transform ? false : new Testopia.TestCaseRun.StatusListStore(cfg.mode == 'local' ? true : false),
loadingText: 'Looking up statuses...',
displayField: 'name',
valueField: 'id',
typeAhead: true,
triggerAction: 'all',
minListWidth: 300,
forceSelection: true,
transform: cfg.transform,
emptyText: 'Please select...'
});
Ext.apply(this, cfg);
this.store.on('load', function(){
if (cfg.value) {
this.setValue(cfg.value);
}
}, this);
};
Ext.extend(Testopia.TestCaseRun.StatusListCombo, Ext.form.ComboBox);
Testopia.TestCaseRun.Panel = function(params, run){
var cgrid = new Testopia.TestCaseRun.Grid(params, run);
var filter = new Testopia.TestCaseRun.Filter();
var cr = new Testopia.TestCaseRun.Info();
this.cgrid = cgrid;
this.store = cgrid.store;
this.params = params;
this.caserun = cr;
filter.flex = 1;
cgrid.flex = 1;
cr.flex = 2;
Testopia.TestCaseRun.Panel.superclass.constructor.call(this, {
layout: 'vbox',
layoutConfig: {
align : 'stretch',
pack  : 'start',
},
title: 'Test Cases',
id: 'caserun-panel',
border: false,
bodyBorder: false,
items: [filter, cgrid, cr]
});
cr.disable();
this.on('activate', this.onActivate, this);
};
Ext.extend(Testopia.TestCaseRun.Panel, Ext.Panel, {
onActivate: function(event){
this.store.load();
}
});
Testopia.TestCaseRun.Filter = function(){
this.form = new Ext.form.BasicForm('caserun_filter_form', {});
var searchform = this.form;
Testopia.TestCaseRun.Filter.superclass.constructor.call(this, {
title: 'Search for Test Results',
id: 'caserun_search',
region: 'north',
border: false,
bodyBorder: false,
layout: 'fit',
split: true,
frame: true,
collapsible: true,
height: 'auto',
autoScroll: true,
contentEl: 'caserun-filter-div',
buttons: [new Ext.form.TextField({
id: 'caserun_save_filter_txt',
validateOnBlur: false,
allowBlank: false
}), {
text: 'Save Filter',
handler: function(){
if (!Ext.getCmp('caserun_save_filter_txt').isValid()) {
Ext.Msg.show({
title: 'Invalid Entry',
msg: 'Please enter a name for this filter',
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.WARNING
});
return false;
}
var testopia_form = new Ext.form.BasicForm('testopia_helper_frm', {});
var params = searchform.getValues();
params.action = 'save_filter';
params.query_name = Ext.getCmp('caserun_save_filter_txt').getValue();
testopia_form.submit({
url: 'tr_process_run.cgi',
params: params,
success: function(){
Ext.getCmp('run_east_panel').activate('run_filter_grid');
Ext.getCmp('run_filter_grid').store.reload();
Testopia.Util.notify.msg('Filter Saved', 'Added filter {0}', params.query_name);
},
failure: Testopia.Util.error
});
}
},        //        new Ext.Toolbar.Fill(),
{
text: 'Reset',
handler: function(){
document.getElementById('caserun_filter_form').reset();
var ds = Ext.getCmp('caserun_grid').store;
var run_id = ds.baseParams.run_id;
var ctype = ds.baseParams.ctype;
ds.baseParams = {};
ds.baseParams.run_id = run_id;
ds.baseParams.ctype = ctype;
ds.baseParams.limit = Ext.getCmp('caserun_pager').pageSize;
ds.load({
callback: function(){
Ext.getCmp('caserun_filtered_txt').hide();
Ext.getCmp('run_filter_grid').getSelectionModel().clearSelections();
if (Ext.getCmp('caserun_grid').getSelectionModel().getCount() < 1) {
Ext.getCmp('caserun-panel').caserun.disable();
}
}
});
}
}, {
text: 'Filter',
handler: function(){
var ds = Ext.getCmp('caserun_grid').store;
ds.baseParams = searchform.getValues();
ds.baseParams.limit = Ext.getCmp('caserun_pager').pageSize;
ds.baseParams.distinct = 1;
ds.load({
callback: function(){
Ext.getCmp('caserun_filtered_txt').show();
if (Ext.getCmp('caserun_grid').getSelectionModel().getCount() < 1) {
Ext.getCmp('caserun-panel').caserun.disable();
}
}
});
}
}]
});
};
Ext.extend(Testopia.TestCaseRun.Filter, Ext.Panel);
Testopia.TestCaseRun.List = function(params, cfg){
this.params = params;
this.store = new Ext.data.GroupingStore({
url: 'tr_list_caseruns.cgi',
baseParams: params,
reader: new Ext.data.JsonReader({
totalProperty: 'totalResultsAvailable',
root: 'Result',
id: 'caserun_id',
fields: [{
name: "caserun_id",
mapping: "case_run_id"
}, {
name: "case_id",
mapping: "case_id"
}, {
name: "run_id",
mapping: "run_id"
}, {
name: "build",
mapping: "build_name"
}, {
name: "environment",
mapping: "env_name"
}, {
name: "assignee",
mapping: "assignee_name"
}, {
name: "testedby",
mapping: "testedby"
}, {
name: "status",
mapping: "status"
}, {
name: "category",
mapping: "category"
}, {
name: "priority",
mapping: "priority"
}, {
name: "close_date",
mapping: "close_date"
}, {
name: "bug_count",
mapping: "bug_count"
}, {
name: "case_summary",
mapping: "case_summary"
}, {
name: "component",
mapping: "component"
}, {
name: "bug_list",
mapping: "bug_list"
}, {
name: "case_bug_list",
mapping: "case_bug_list"
}, {
name: "plan_name", 
mapping:"plan_name"
}]
}),
remoteSort: true,
sortInfo: {
field: 'run_id',
direction: "ASC"
},
groupField: 'run_id'
});
var ds = this.store;
ds.paramNames.sort = "order";
ds.on('beforeload', function(store, o){
store.baseParams.ctype = 'json';
});
this.summary_sort = function(){
this.store.sortInfo.field = 'summary';
this.store.sortInfo.direction == 'DESC' ? this.store.sortInfo.direction = 'ASC' : this.store.sortInfo.direction = 'DESC';
this.getView().mainHd.select('td').removeClass(this.getView().sortClasses);
this.store.load();
};
this.bbar = new Testopia.Util.PagingBar('caserun', this.store);
this.columns = [{
header: "Case",
width: 50,
dataIndex: 'case_id',
sortable: true,
groupRenderer: function(v){
return v;
},
renderer: Testopia.Util.makeLink.createDelegate(this,['case'],true)
}, {
header: "Run",
width: 50,
dataIndex: 'run_id',
sortable: true,
groupRenderer: function(v){
return v;
},
renderer: Testopia.Util.makeLink.createDelegate(this,['run'],true)
}, {
header: "Build",
width: 50,
dataIndex: 'build',
sortable: true,
id: 'caserun_list_build_col'
}, {
header: "Environment",
width: 50,
dataIndex: 'environment',
sortable: true
}, {
header: "Assignee",
width: 150,
sortable: true,
dataIndex: 'assignee'
}, {
header: "Tested By",
width: 150,
sortable: true,
dataIndex: 'testedby'
}, {
header: "Status",
width: 30,
sortable: true,
dataIndex: 'status',
groupRenderer: function(v){
return v;
},
renderer: Testopia.Util.displayStatusIcon
}, {
header: "Closed",
width: 60,
sortable: true,
dataIndex: 'close_date'
}, {
header: "Priority",
width: 60,
sortable: true,
dataIndex: 'priority'
}, {
header: "Category",
width: 100,
sortable: true,
dataIndex: 'category'
}, {
header: "Component",
width: 100,
sortable: true,
dataIndex: 'component'
},{
header: "Plan Name",
width: 100,
sortable: true,
hidden: true,
dataIndex: 'plan_name'
}, {
header: "Bugs In This Build and Environment",
width: 100,
dataIndex: "bug_list",
sortable: false,
hideable: true,
renderer: function(v){
var bugs = v.bugs;
var rets = '';
for (var i = 0; i < bugs.length; i++) {
if (typeof bugs[i] != 'function') {
rets = rets + '<a href="show_bug.cgi?id=' + bugs[i].bug_id + '" ' + (bugs[i].closed ? 'class="bz_closed"' : '') + '>' + bugs[i].bug_id + '</a>, ';
}
}
return rets;
}
}, {
header: "Bugs In All Builds and Environments",
width: 100,
dataIndex: "case_bug_list",
sortable: false,
hideable: true,
renderer: function(v){
var bugs = v.bugs;
var rets = '';
for (var i = 0; i < bugs.length; i++) {
if (typeof bugs[i] != 'function') {
rets = rets + '<a href="show_bug.cgi?id=' + bugs[i].bug_id + '" ' + (bugs[i].closed ? 'class="bz_closed"' : '') + '>' + bugs[i].bug_id + '</a>, ';
}
}
return rets;
}
}];
this.view = new Ext.grid.GroupingView({
forceFit: true,
groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Items" : "Item"]})',
enableRowBody: true,
getRowClass: function(record, rowIndex, p, ds){
p.body = '<p><a href="javascript:Ext.getCmp(\'caserun_list_grid\').summary_sort()">Summary:</a> ' + record.data.case_summary + '</p>';
return 'x-grid3-row-expanded';
}
});
this.tbar = [new Ext.Toolbar.Fill(), 
{
xtype: 'button',
id: 'caserun_grid_tocsv',
icon: 'extensions/testopia/img/csv.png',
iconCls: 'img_button_16x',
tooltip: 'Export Results to CSV',
handler: function(){
window.location = 'tr_list_caseruns.cgi?ctype=csv&viewall=1&' + Testopia.Util.JSONToURLQuery( Ext.getCmp(cfg.id || 'caserun_list_grid').store.baseParams, '', ['viewall', 'ctype']);
}
},{
xtype: 'button',
id: 'save_caserun_list_btn',
icon: 'extensions/testopia/img/save.png',
iconCls: 'img_button_16x',
tooltip: 'Save this search',
handler: function(b, e){
Testopia.Search.save('caserun', Ext.getCmp(cfg.id || 'caserun_list_grid').store.baseParams);
}
}, {
xtype: 'button',
id: 'link_case_list_btn',
icon: 'extensions/testopia/img/link.png',
iconCls: 'img_button_16x',
tooltip: 'Create a link to this list',
handler: function(b, e){
Testopia.Search.LinkPopup(Ext.getCmp(cfg.id || 'caserun_list_grid').store.baseParams);
}
}];
Testopia.TestCaseRun.List.superclass.constructor.call(this, {
id: cfg.id || 'caserun_list_grid',
title: 'Case Run History',
loadMask: {
msg: 'Loading Test Cases...'
},
layout: 'fit',
region: 'center',
stripeRows: true,
autoExpandColumn: "caserun_list_build_col",
autoScroll: true,
sm: new Ext.grid.RowSelectionModel({
singleSelect: false
}),
viewConfig: {
forceFit: true
}
});
Ext.apply(this, cfg);
this.on('activate', this.onActivate, this);
};
Ext.extend(Testopia.TestCaseRun.List, Ext.grid.GridPanel, {
deleteList: function(){
var grid = this;
Ext.Msg.show({
title: 'Confirm Delete?',
msg: CASERUN_DELETE_WARNING,
buttons: Ext.Msg.YESNO,
animEl: 'caserun-delete-btn',
icon: Ext.MessageBox.QUESTION,
fn: function(btn){
if (btn == 'yes') {
var testopia_form = new Ext.form.BasicForm('testopia_helper_frm');
testopia_form.submit({
url: 'tr_list_caseruns.cgi',
params: {
caserun_ids: Testopia.Util.getSelectedObjects(grid, 'caserun_id'),
action: 'delete',
deltype: 'cr',
single: true,
ctype: 'json'
},
success: function(data){
Ext.Msg.show({
msg: "Test cases removed",
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.INFO
});
grid.store.reload();
},
failure: function(f, a){
Testopia.Util.error(f, a);
grid.store.reload();
}
});
}
}
});
},
onActivate: function(event){
if (!this.store.getCount()) {
this.store.load();
}
}
});
Testopia.TestCaseRun.Grid = function(params, run){
params.limit = Ext.state.Manager.get('TESTOPIA_DEFAULT_PAGE_SIZE', 25);
this.params = params;
this.run = run;
var testopia_form = new Ext.form.BasicForm('testopia_helper_frm', {});
var selected;
this.summary_sort = function(){
this.store.sortInfo.field = 'summary';
this.store.sortInfo.direction == 'DESC' ? this.store.sortInfo.direction = 'ASC' : this.store.sortInfo.direction = 'DESC';
this.getView().mainHd.select('td').removeClass(this.getView().sortClasses);
this.store.load();
};
envRenderer = function(v, md, r, ri, ci, s){
var f = this.getColumnModel().getCellEditor(ci, ri).field;
record = f.store.getById(v);
if (record) {
return '<a href="tr_environments.cgi?env_id=' + record.data[f.valueField] + '">' + record.data[f.displayField] + '</a>';
}
else {
return '<a href="tr_environments.cgi?env_id=' + r.data.env_id + '">' + v + '</a>';
}
};
this.store = new Ext.data.GroupingStore({
url: 'tr_list_caseruns.cgi',
baseParams: params,
reader: new Ext.data.JsonReader({
totalProperty: 'totalResultsAvailable',
root: 'Result',
id: 'caserun_id',
fields: [{
name: "caserun_id",
mapping: "case_run_id"
}, {
name: "sortkey",
mapping: "sortkey"
}, {
name: "case_id",
mapping: "case_id"
}, {
name: "run_id",
mapping: "run_id"
}, {
name: "build",
mapping: "build_name"
}, {
name: "environment",
mapping: "env_name"
}, {
name: "env_id",
mapping: "env_id"
}, {
name: "assignee",
mapping: "assignee_name"
}, {
name: "testedby",
mapping: "testedby"
}, {
name: "status",
mapping: "status"
}, {
name: "requirement",
mapping: "requirement"
}, {
name: "category",
mapping: "category"
}, {
name: "priority",
mapping: "priority"
}, {
name: "close_date",
mapping: "close_date"
}, {
name: "bug_count",
mapping: "bug_count"
}, {
name: "case_summary",
mapping: "case_summary"
}, {
name: "type",
mapping: "type"
}, {
name: "id",
mapping: "id"
}, {
name: "component",
mapping: "component"
}, {
name: "bug_list",
mapping: "bug_list"
}, {
name: "case_bug_list",
mapping: "case_bug_list"
}, {
name: "plan_name", 
mapping:"plan_name"
}]
}),
remoteSort: true,
sortInfo: {
field: 'sortkey',
direction: "ASC"
},
groupField: 'run_id'
});
var ds = this.store;
ds.paramNames.sort = "order";
ds.on('beforeload', function(store, o){
store.baseParams.ctype = 'json';
});
var buildCombo = new Testopia.Build.Combo({
id: 'tb_build',
width: 100,
fieldLabel: 'Build',
hiddenName: 'build',
mode: 'remote',
forceSelection: false,
allowBlank: false,
typeAhead: true,
disabled: true,
params: {
product_id: run.plan.product_id,
activeonly: 1
}
});
var envCombo = new Testopia.Environment.Combo({
id: 'tb_environment',
width: 100,
fieldLabel: 'Environment',
hiddenName: 'environment',
mode: 'remote',
forceSelection: false,
allowBlank: false,
typeAhead: true,
disabled: true,
params: {
product_id: run.plan.product_id,
isactive: 1
}
});
buildCombo.on('select', function(c, r, i){
params = {
build_id: r.get('id'),
ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id')
};
Testopia.Util.updateFromList('caserun', params, Ext.getCmp('caserun_grid'));
});
envCombo.on('select', function(c, r, i){
params = {
env_id: r.get('environment_id'),
ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id')
};
Testopia.Util.updateFromList('caserun', params, Ext.getCmp('caserun_grid'));
});
this.object_type = 'environment';
this.columns = [{
header: "Case",
width: 50,
dataIndex: 'case_id',
sortable: true,
renderer: Testopia.Util.makeLink.createDelegate(this,['case'],true)
}, {
header: "Run",
width: 50,
dataIndex: 'run_id',
sortable: true,
renderer: Testopia.Util.makeLink.createDelegate(this,['run'],true),
hidden: true
}, {
header: "Index",
width: 50,
dataIndex: 'sortkey',
sortable: true,
editor: new Ext.grid.GridEditor(new Ext.form.NumberField())
}, {
header: "Build",
width: 50,
dataIndex: 'build',
sortable: true,
editor: new Ext.grid.GridEditor(new Testopia.Build.Combo({
params: {
product_id: run.plan.product_id,
activeonly: 1
}
})),
renderer: Testopia.Util.ComboRenderer.createDelegate(this)
}, {
header: "Environment",
width: 50,
dataIndex: 'environment',
sortable: true,
editor: new Ext.grid.GridEditor(new Testopia.Environment.Combo({
params: {
product_id: run.plan.product_id,
isactive: 1
}
})),
renderer: envRenderer.createDelegate(this)
}, {
header: "Assignee",
width: 150,
sortable: true,
dataIndex: 'assignee',
editor: new Ext.grid.GridEditor(new Testopia.User.Lookup({
id: 'caserun_assignee'
})),
renderer: Testopia.Util.ComboRenderer.createDelegate(this)
}, {
header: "Tested By",
width: 150,
sortable: true,
dataIndex: 'testedby',
hidden: true
}, {
header: "Closed",
width: 90,
sortable: true,
dataIndex: 'close_date'
}, {
header: "Status",
width: 30,
sortable: true,
dataIndex: 'status',
align: 'center',
renderer: Testopia.Util.displayStatusIcon
}, {
header: "Priority",
width: 60,
sortable: true,
dataIndex: 'priority',
editor: new Ext.grid.GridEditor(new Testopia.TestCase.PriorityCombo({
id: 'caserun_priority'
})),
renderer: Testopia.Util.ComboRenderer.createDelegate(this)
}, {
header: "Category",
width: 100,
sortable: true,
dataIndex: 'category',
editor: new Ext.grid.GridEditor(new Testopia.Category.Combo({
id: 'caserun_category',
params: {
product_id: run.plan.product_id
}
})),
renderer: Testopia.Util.ComboRenderer.createDelegate(this)
}, {
header: "Requirement",
width: 150,
sortable: true,
dataIndex: 'requirement',
hidden: true
}, {
header: "Component",
width: 100,
sortable: true,
dataIndex: 'component'
}, {
header: "Plan Name",
width: 100,
sortable: true,
hidden: true,
dataIndex: 'plan_name'
}, {
header: "Bugs In This Build and Environment",
width: 100,
dataIndex: "bug_list",
sortable: false,
hideable: true,
renderer: function(v){
var bugs = v.bugs;
var rets = '';
for (var i = 0; i < bugs.length; i++) {
if (typeof bugs[i] != 'function') {
rets = rets + '<a href="show_bug.cgi?id=' + bugs[i].bug_id + '" ' + (bugs[i].closed ? 'class="bz_closed"' : '') + '>' + bugs[i].bug_id + '</a>, ';
}
}
return rets;
}
}, {
header: "Bugs In All Builds and Environments",
width: 100,
dataIndex: "case_bug_list",
sortable: false,
hideable: true,
renderer: function(v){
var bugs = v.bugs;
var rets = '';
for (var i = 0; i < bugs.length; i++) {
if (typeof bugs[i] != 'function') {
rets = rets + '<a href="show_bug.cgi?id=' + bugs[i].bug_id + '" ' + (bugs[i].closed ? 'class="bz_closed"' : '') + '>' + bugs[i].bug_id + '</a>, ';
}
}
return rets;
}
}];
this.form = new Ext.form.BasicForm('testopia_helper_frm', {});
this.bbar = new Testopia.Util.PagingBar('caserun', this.store);
this.tbar = new Ext.Toolbar({
id: 'caserun_grid_tb',
items: [{
xtype: 'button',
template: imgButtonTpl,
text: 'extensions/testopia/img/IDLE.gif',
tooltip: 'Mark as IDLE (Not Run)',
disabled: true,
handler: function(){
Testopia.Util.updateFromList('caserun', {
status_id: 1,
ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id')
}, Ext.getCmp('caserun_grid'));
}
}, {
xtype: 'button',
template: imgButtonTpl,
text: 'extensions/testopia/img/PASSED.gif',
tooltip: 'Mark as PASSED',
disabled: true,
handler: function(){
Testopia.Util.updateFromList('caserun', {
status_id: 2,
ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id'),
update_bug: Ext.getCmp('update_bugs').getValue()
}, Ext.getCmp('caserun_grid'));
}
}, {
xtype: 'button',
template: imgButtonTpl,
text: 'extensions/testopia/img/FAILED.gif',
tooltip: 'Mark as FAILED',
disabled: true,
handler: function(){
Testopia.Util.updateFromList('caserun', {
status_id: 3,
ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id'),
update_bug: Ext.getCmp('update_bugs').getValue()
}, Ext.getCmp('caserun_grid'));
}
}, {
xtype: 'button',
template: imgButtonTpl,
text: 'extensions/testopia/img/RUNNING.gif',
tooltip: 'Mark as RUNNING',
disabled: true,
handler: function(){
var reassign = 0;
var isowner = 1;
var sel = Ext.getCmp('caserun_grid').getSelectionModel().getSelections();
for (var i = 0; i < sel.length; i++) {
if (sel[i].get('assignee') != user_login) {
isowner = 0;
break;
}
}
if (isowner == 0) {
Ext.Msg.show({
title: "Reassign Test Case?",
msg: 'Setting this test case to Running will lock it so that only the assignee can update it. Would you like to make yourself the assignee?',
buttons: Ext.MessageBox.YESNO,
icon: Ext.MessageBox.QUESTION,
fn: function(btn){
if (btn == 'yes') {
reassign = 1;
}
Testopia.Util.updateFromList('caserun', {
status_id: 4,
reassign: reassign,
ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id')
}, Ext.getCmp('caserun_grid'));
}
});
}
else {
Testopia.Util.updateFromList('caserun', {
status_id: 4,
reassign: reassign,
ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id')
}, Ext.getCmp('caserun_grid'));
}
}
}, {
xtype: 'button',
template: imgButtonTpl,
text: 'extensions/testopia/img/PAUSED.gif',
tooltip: 'Mark as PAUSED',
disabled: true,
handler: function(){
Testopia.Util.updateFromList('caserun', {
status_id: 5,
ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id')
}, Ext.getCmp('caserun_grid'));
}
}, {
xtype: 'button',
template: imgButtonTpl,
text: 'extensions/testopia/img/BLOCKED.gif',
tooltip: 'Mark as BLOCKED',
disabled: true,
handler: function(){
Testopia.Util.updateFromList('caserun', {
status_id: 6,
ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id')
}, Ext.getCmp('caserun_grid'));
}
}, {
xtype: 'button',
template: imgButtonTpl,
text: 'extensions/testopia/img/ERROR.gif',
tooltip: 'Mark as ERROR',
disabled: true,
handler: function(){
Testopia.Util.updateFromList('caserun', {
status_id: 7,
ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id')
}, Ext.getCmp('caserun_grid'));
}
}, ' ', '-', 'Update Bugs: ', new Ext.form.Checkbox({
id: 'update_bugs',
disabled: true
}), ' ', '-', ' ', buildCombo, ' ', envCombo, new Ext.Toolbar.Fill(), 
{
xtype: 'button',
id: 'caserun_grid_tocsv',
icon: 'extensions/testopia/img/csv.png',
iconCls: 'img_button_16x',
tooltip: 'Export Results to CSV',
handler: function(){
window.location = 'tr_list_caseruns.cgi?ctype=csv&viewall=1&run_id=' + run.run_id;
}
}, {
xtype: 'button',
id: 'add_case_to_run_btn',
tooltip: "Add cases to this run",
icon: 'extensions/testopia/img/add.png',
iconCls: 'img_button_16x',
handler: function(){
Testopia.TestRun.AddCasePopup(run);
}
}, {
xtype: 'button',
id: 'new_case_to_run_btn',
tooltip: "Create a new case and add it to this run",
icon: 'extensions/testopia/img/new.png',
iconCls: 'img_button_16x',
handler: function(){
Testopia.TestCase.NewCasePopup(run.plan_id, run.product_id, run.run_id);
}
}, {
xtype: 'button',
id: 'caserun_grid_edit_btn',
icon: 'extensions/testopia/img/edit.png',
iconCls: 'img_button_16x',
tooltip: 'Edit Selected Test Case',
handler: function(){
Testopia.Util.editFirstSelection(Ext.getCmp('caserun_grid'));
}
}, {
xtype: 'button',
id: 'caserun_grid_delete_btn',
icon: 'extensions/testopia/img/delete.png',
iconCls: 'img_button_16x',
tooltip: 'Remove Selected Test Cases from This Run',
handler: this.deleteList.createDelegate(this)
}, new Testopia.TestRun.ProgressBar({
id: 'run_progress',
text: '0%',
width: 100
})]
});
Testopia.TestCaseRun.Grid.superclass.constructor.call(this, {
region: 'center',
id: 'caserun_grid',
border: false,
bodyBorder: false,
height: '400',
stripeRows: true,
split: true,
enableDragDrop: true,
loadMask: {
msg: 'Loading Test Cases...'
},
autoExpandColumn: "case_summary",
autoScroll: true,
sm: new Ext.grid.RowSelectionModel({
singleSelect: false,
listeners: {
'rowdeselect': function(sm, n, r){
if (sm.getCount() < 1) {
Ext.getCmp('case_details_panel').disable();
Ext.getCmp('tb_build').disable();
Ext.getCmp('tb_environment').disable();
Ext.getCmp('update_bugs').disable();
var items = this.grid.getTopToolbar().items.items;
for (var i = 0; i < items.length; i++) {
if ((items[i].id == 'add_case_to_run_btn' || items[i].id == 'run_progress')) {
if (Ext.getCmp('run_status_cycle').text == 'RUNNING') {
items[i].enable();
}
}
else {
items[i].disable();
}
}
}
},
'rowselect': function(sm, n, r){
Ext.getCmp('case_details_panel').enable();
if (Ext.getCmp('run_status_cycle').text == 'RUNNING') {
Ext.getCmp('summary_tb').enable();
Ext.getCmp('tb_build').enable();
Ext.getCmp('tb_environment').enable();
Ext.getCmp('update_bugs').enable();
var items = sm.grid.getTopToolbar().items.items;
for (var i = 0; i < items.length; i++) {
items[i].enable();
}
}
if (n == selected) {
return;
}
var sel = [];
for (i = 0; i < sm.grid.store.data.items.length; i++) {
if (sm.grid.getSelectionModel().isSelected(i)) {
sel.push(sm.grid.store.getAt(i).get('case_id'));
}
}
sm.grid.selectedRows = sel;
if (sm.getCount() > 1) {
return;
}
Ext.getCmp('case_bugs_panel').tcid = r.get('case_id');
Ext.getCmp('case_comps_panel').tcid = r.get('case_id');
Ext.getCmp('attachments_panel').object = r.data;
Ext.getCmp('case_details_panel').caserun_id = r.get('caserun_id');
Ext.getCmp('casetagsgrid').obj_id = r.get('case_id');
var tab = Ext.getCmp('caserun_center_region').getActiveTab();
Ext.getCmp(tab.id).fireEvent('activate');
if (Ext.getCmp('case_bugs_panel')) {
Ext.getCmp('case_bugs_panel').case_id = r.get('case_id');
}
if (Ext.getCmp('case_bugs_panel')) {
Ext.getCmp('case_bugs_panel').case_id = r.get('case_id');
}
Ext.getCmp('case_details_panel').store.load({
params: {
caserun_id: r.get('caserun_id'),
action: 'gettext'
}
});
selected = n;
}
}
}),
viewConfig: {
forceFit: true,
enableRowBody: true,
getRowClass: function(record, rowIndex, p, ds){
p.body = '<p><a href="javascript:Ext.getCmp(\'caserun_grid\').summary_sort()">Summary:</a> ' + record.data.case_summary + '</p>';
return 'x-grid3-row-expanded';
}
}
});
this.on('rowcontextmenu', this.onContextClick, this);
this.on('afteredit', this.onGridEdit, this);
this.on('activate', this.onActivate, this);
};
Ext.extend(Testopia.TestCaseRun.Grid, Ext.grid.EditorGridPanel, {
onContextClick: function(grid, index, e){
grid.selindex = index;
if (!this.menu) { // create context menu on first right click
this.menu = new Ext.menu.Menu({
id: 'caserun-ctx-menu',
items: [{
text: 'Change',
icon: 'extensions/testopia/img/edit.png',
iconCls: 'img_button_16x',
menu: {
items: [{
text: 'Build',
handler: function(){
var win = new Ext.Window({
title: 'Edit Build',
id: 'status-win',
plain: true,
shadow: false,
width: 320,
height: 150,
listeners: {'afterlayout':function(){Ext.getCmp('multi_build').focus('',10)}},
layout: 'form',
bodyStyle: 'padding: 5px',
items: [new Testopia.Build.Combo({
params: {
product_id: grid.run.plan.product_id,
activeonly: 1
},
fieldLabel: 'Build',
id: 'multi_build'
}), new Ext.form.Checkbox({
fieldLabel: 'Apply to all cases in this run',
id: 'build_applyall'
})],
buttons: [{
text: 'Submit',
handler: function(){
params = {
run_id: grid.run.run_id,
applyall: Ext.getCmp('build_applyall').getValue(),
build_id: Ext.getCmp('multi_build').getValue(),
ids: Testopia.Util.getSelectedObjects(grid, 'caserun_id')
};
Testopia.Util.updateFromList('caserun', params, grid);
win.close();
}
}, {
text: 'Close',
handler: function(){
win.close();
}
}]
});
win.show(this);
}
}, {
text: 'Environment',
handler: function(){
var win = new Ext.Window({
title: 'Edit Environment',
id: 'status-win',
plain: true,
shadow: false,
width: 320,
height: 150,
listeners: {'afterlayout':function(){Ext.getCmp('multi_env').focus('',10)}},
layout: 'form',
bodyStyle: 'padding: 5px',
items: [new Testopia.Environment.Combo({
params: {
product_id: grid.run.plan.product_id,
isactive: 1
},
fieldLabel: 'Environment',
id: 'multi_env'
}), new Ext.form.Checkbox({
fieldLabel: 'Apply to all cases in this run',
id: 'env_applyall'
})],
buttons: [{
text: 'Submit',
handler: function(){
params = {
run_id: grid.run.run_id,
applyall: Ext.getCmp('env_applyall').getValue(),
env_id: Ext.getCmp('multi_env').getValue(),
ids: Testopia.Util.getSelectedObjects(grid, 'caserun_id')
};
Testopia.Util.updateFromList('caserun', params, grid);
win.close();
}
}, {
text: 'Close',
handler: function(){
win.close();
}
}]
});
win.show(this);
}
}, {
text: 'Priority',
handler: function(){
var win = new Ext.Window({
title: 'Edit Priority',
id: 'priority-win',
plain: true,
shadow: false,
width: 320,
height: 150,
listeners: {'afterlayout':function(){Ext.getCmp('multi_priority').focus('',10)}},
layout: 'form',
bodyStyle: 'padding: 5px',
items: [new Testopia.TestCase.PriorityCombo({
fieldLabel: 'Priority',
id: 'multi_priority'
})],
buttons: [{
text: 'Submit',
handler: function(){
params = {
run_id: grid.run.run_id,
priority: Ext.getCmp('multi_priority').getValue(),
ids: Testopia.Util.getSelectedObjects(grid, 'caserun_id')
};
Testopia.Util.updateFromList('caserun', params, grid);
win.close();
}
}, {
text: 'Close',
handler: function(){
win.close();
}
}]
});
win.show(this);
}
}, {
text: 'Category',
handler: function(){
var win = new Ext.Window({
title: 'Edit Category',
id: 'status-win',
plain: true,
shadow: false,
width: 300,
height: 150,
listeners: {'afterlayout':function(){Ext.getCmp('multi_category').focus('',10)}},
items: [new Testopia.Category.Combo({
fieldLabel: 'Category',
id: 'multi_category',
params: {
product_id: run.product_id
}
})],
buttons: [{
text: 'Submit',
handler: function(){
Testopia.Util.updateFromList('case', {
category: Ext.getCmp('case_category_combo').getValue(),
ids: Testopia.Util.getSelectedObjects(grid, 'case_id')
}, grid);
win.close();
}
}, {
text: 'Close',
handler: function(){
win.close();
}
}]
});
win.show(this);
}
}, {
text: 'Assignee',
handler: function(){
var win = new Ext.Window({
title: 'Edit Assignee',
id: 'status-win',
plain: true,
shadow: false,
width: 320,
height: 150,
listeners: {'afterlayout':function(){Ext.getCmp('multi_assignee').focus('',10)}},
layout: 'form',
bodyStyle: 'padding: 5px',
items: [new Testopia.User.Lookup({
fieldLabel: 'Assignee',
id: 'multi_assignee'
}), new Ext.form.Checkbox({
fieldLabel: 'Apply to all cases in this run',
id: 'assignee_applyall'
})],
buttons: [{
text: 'Submit',
handler: function(){
params = {
run_id: grid.run.run_id,
applyall: Ext.getCmp('assignee_applyall').getValue(),
assignee: Ext.getCmp('multi_assignee').getValue(),
ids: Testopia.Util.getSelectedObjects(grid, 'caserun_id')
};
Testopia.Util.updateFromList('caserun', params, grid);
win.close();
}
}, {
text: 'Close',
handler: function(){
win.close();
}
}]
});
win.show(this);
}
}]
}
}, {
text: 'Remove Selected Cases',
icon: 'extensions/testopia/img/delete.png',
iconCls: 'img_button_16x',
handler: this.deleteList.createDelegate(this)
}, {
text: 'Add or Remove Tags',
handler: function(){
Testopia.Tags.update('case', grid);
}
}, {
text: 'New Test Run',
id: 'addRun',
handler: function(){
window.location = "tr_new_run.cgi?plan_id=" + run.plan_id;
}
}, {
text: 'Clone Run with Selected Cases',
handler: function(){
Testopia.TestRun.ClonePopup(grid.run.product_id, grid.run.run_id, Testopia.Util.getSelectedObjects(grid, 'case_id'));
}
}, {
text: 'Copy or Link Selected Test Cases to Plan(s)... ',
handler: function(){
var r = grid.getSelectionModel().getSelected();
Testopia.TestCase.clonePopup(grid.run.product_id, Testopia.Util.getSelectedObjects(grid, 'case_id'));
}
}, {
text: 'Add Selected Test Cases to Run... ',
handler: function(){
Ext.Msg.prompt('Add to runs', '', function(btn, text){
if (btn == 'ok') {
Testopia.Util.updateFromList('case', {
addruns: text,
ids: Testopia.Util.getSelectedObjects(grid, 'case_id')
}, grid);
}
});
}
}, {
text: 'Refresh List',
icon: 'extensions/testopia/img/refresh.png',
iconCls: 'img_button_16x',
handler: function(){
grid.store.reload();
}
}, {
text: 'View Test Case in a New Window',
handler: function(){
window.open('tr_show_case.cgi?case_id=' + grid.store.getAt(grid.selindex).get('case_id'));
}
}, {
text: 'List These Test Cases in a New Window',
handler: function(){
var params = Ext.getCmp('caserun_search').form.getValues();
if (params) {
window.open('tr_list_cases.cgi?' + Testopia.Util.JSONToURLQuery(params, '', ['current_tab']) + '&isactive=1');
}
else {
window.open('tr_list_cases.cgi?run_id=' + grid.store.getAt(grid.selindex).get('run_id'));
}
}
}]
});
}
e.stopEvent();
if (grid.getSelectionModel().getCount() < 1) {
grid.getSelectionModel().selectRow(index);
}
this.menu.showAt(e.getXY());
},
onGridEdit: function(gevent){
var myparams = {
caserun_id: gevent.record.get('caserun_id')
};
var ds = this.store;
switch (gevent.field) {
case 'sortkey':
myparams.action = 'update_sortkey';
myparams.sortkey = gevent.value;
break;
case 'build':
myparams.action = 'update_build';
myparams.build_id = gevent.value;
break;
case 'environment':
myparams.action = 'update_environment';
myparams.caserun_env = gevent.value;
break;
case 'assignee':
myparams.action = 'update_assignee';
myparams.assignee = gevent.value;
break;
case 'priority':
myparams.action = 'update_priority';
myparams.priority = gevent.value;
break;
case 'category':
myparams.action = 'update_category';
myparams.category = gevent.value;
break;
}
this.form.submit({
url: "tr_caserun.cgi",
params: myparams,
success: function(f, a){
if (a.result.caserun) {
var switched = gevent.grid.store.reader.readRecords({
Result: [a.result.caserun]
}).records[0];
gevent.grid.store.insert(gevent.row, switched);
ds.commitChanges();
gevent.grid.store.remove(gevent.record);
gevent.grid.getSelectionModel().selectRow(gevent.row);
}
else {
ds.commitChanges();
}
},
failure: function(f, a){
Testopia.Util.error(f, a);
ds.rejectChanges();
}
});
},
deleteList: function(){
var grid = this;
if (grid.getSelectionModel().getCount() < 1) {
return;
}
var win = new Ext.Window({
title: 'Confirm Delete?',
id: 'case_delete_win',
plain: true,
shadow: false,
width: 520,
height: 250,
layout: 'table',
bodyStyle: 'padding: 5px',
layoutConfig: {
columns: 1,
width: '100%'
},
items: [{
html: CASERUN_DELETE_WARNING,
bodyStyle: 'padding: 5px; font-weight:bold; color: red'
}, {
xtype: 'fieldset',
items:[{
xtype: 'radio',
name: 'delete_cases_options',
id: 'delete_cases_radio_group',
inputValue: 'cr_all',
checked: true,
boxLabel: 'Remove case from this run for all builds and environments',
hideLabel: true
}, {
xtype: 'radio',
name: 'delete_cases_options',
inputValue: 'cr',
boxLabel: 'Remove case from this run for SELECTED build and environment only',
hideLabel: true
}, {
xtype: 'radio',
name: 'delete_cases_options',
inputValue: 'plan_single',
boxLabel: 'Remove case from this run and from this test plan',
hideLabel: true
}, {
xtype: 'radio',
name: 'delete_cases_options',
inputValue: 'all_plans',
boxLabel: 'Delete this case completely (remove from all test plans)',
hideLabel: true
}]
}],
buttons: [{
text: 'Submit',
handler: function(){
var testopia_form = new Ext.form.BasicForm('testopia_helper_frm');
testopia_form.submit({
url: 'tr_list_caseruns.cgi',
params: {
caserun_ids: Testopia.Util.getSelectedObjects(grid, 'caserun_id'),
action: 'delete',
deltype: Ext.getCmp('delete_cases_radio_group').getGroupValue(),
ctype: 'json'
},
success: function(data){
Ext.Msg.show({
msg: "Test cases removed",
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.INFO
});
grid.store.reload();
},
failure: function(f, a){
Testopia.Util.error(f, a);
grid.store.reload();
}
});
win.close();
}
}, {
text: 'Cancel',
handler: function(){
win.close();
}
}]
});
win.show(this);
},
onActivate: function(event){
if (!this.store.getCount()) {
this.store.load();
}
}
});
var processText;
Testopia.TestCaseSetupBreakdownPanel = function(params)
{
params = params || {};
return {
layout: 'column',
columnWidth: 1.0,
title: 'Set Up / Break Down',
items: [{
columnWidth:0.5,
layout:'fit',
items:{
title: 'Setup',
height: Ext.state.Manager.get('bigtext_height', 500),
bodyBorder: false,
border: false,
id: 'cr_setup_panel',
autoScroll: true,
layout: 'fit',
items: Testopia.TestCaseTextEditor('setup', params)
}
},{
columnWidth:0.5,
layout:'fit',
items:{
title: 'Breakdown',
height: Ext.state.Manager.get('bigtext_height', 500),
bodyBorder: false,
border: false,
id: 'cr_breakdown_panel',
autoScroll: true,
layout: 'fit',
items: Testopia.TestCaseTextEditor('breakdown', params)
}
}],
buttons: [{
text: 'Save',
handler: processText
}]
};
};
Testopia.TestCaseTextEditor = function(id, data)
{
if (Param_Use_HTMLEditor)
return [{
id: id+'_editor',
xtype: 'htmleditor',
value: data[id]||''
}];
else
return [{
id: id+'_editor',
html: data[id]||'',
height: 'auto'
},{
id: id+'_textarea',
xtype: 'textarea',
style: 'font-family: monospace',
width: '100%',
height: '100%',
hidden: true,
value: data[id]||''
}];
};
Testopia.TestCaseShowHTMLEditor = function()
{
var s, h;
var editorids = { 'action': 1, 'effect': 1 };
if (Param_Show_Setup_Breakdown)
editorids['setup'] = editorids['breakdown'] = 1;
var b = Ext.getCmp('edit_html_button');
var b1 = Ext.getCmp('save_html_button');
if (Ext.getCmp('action_editor').hidden)
{
b.setText('Edit HTML source');
b1.hide();
s = 'hide', h = 'show';
for (var i in editorids)
Ext.getCmp(i+'_editor').body.update(Ext.getCmp(i+'_textarea').getValue());
}
else
{
b1.show();
b.setText('Close editor');
s = 'show', h = 'hide';
}
for (var i in editorids)
{
Ext.getCmp(i+'_editor')[h]();
Ext.getCmp(i+'_textarea')[s]();
}
};
Testopia.TestCaseUpdateTextForId = function(id)
{
var testopia_form = new Ext.form.BasicForm('testopia_helper_frm', {});
var params = {};
var a = Param_Use_HTMLEditor ? '_editor' : '_textarea';
var editorids = { 'action': 1, 'effect': 1 };
if (Param_Show_Setup_Breakdown)
editorids['setup'] = editorids['breakdown'] = 1;
for (var i in editorids)
params['tc'+i] = Ext.getCmp(i+a).getValue();
params.case_id = id;
params.action = 'update_doc';
testopia_form.submit({
url: 'tr_process_case.cgi',
params: params,
success: function(){
Testopia.Util.notify.msg('Test case updated', 'Test Case {0} was updated successfully', 'Document');
},
failure: Testopia.Util.error
});
};
Testopia.TestCaseShowEffectEditor = function()
{
var d = Ext.getCmp('effect_editor_col');
if (!d.hidden)
{
Ext.getCmp('action_editor_col').columnWidth = 1.0;
Ext.getCmp('showhide_results_btn').setText('Show Results');
d.hide();
}
else
{
Ext.getCmp('action_editor_col').columnWidth = 0.5;
Ext.getCmp('showhide_results_btn').setText('Hide Results');
d.show();
}
Ext.getCmp('action_panel').doLayout();
};
Testopia.TestCaseActionPanel = function(data)
{
data = data || {};
var actionResultsButtons = [{
text: data.effect ? 'Hide Results' : 'Show Results',
id: 'showhide_results_btn',
handler: Testopia.TestCaseShowEffectEditor
}];
if (Param_Use_HTMLEditor)
{
actionResultsButtons.unshift({
text: 'Update Action/Results',
handler: Testopia.TestCaseUpdateText
});
}
else
{
actionResultsButtons.unshift({
text: 'Save',
id: 'save_html_button',
hidden: true,
handler: Testopia.TestCaseUpdateText
}, {
text: 'Edit HTML source',
id: 'edit_html_button',
handler: Testopia.TestCaseShowHTMLEditor
});
}
var h = Ext.state.Manager.get('bigtext_height', 500);
if (!h || h != h)
h = 500;
return {
layout: 'column',
columnWidth: 1.0,
title: 'Description',
id: 'action_panel',
items: [{
columnWidth: data.effect ? 0.5 : 1.0,
layout: 'fit',
id: 'action_editor_col',
items:[{
title: 'Action',
height: h,
id: 'cr_action_panel',
bodyBorder: false,
border: false,
layout: 'fit',
autoScroll: true,
items: Testopia.TestCaseTextEditor('action', data)
}]
}, {
columnWidth: 0.5,
id: 'effect_editor_col',
layout: 'fit',
forceLayout: true,
hidden: !data.effect,
items: {
title: 'Expected Results',
height: h,
id: 'cr_results_panel',
bodyBorder: false,
border: false,
layout: 'fit',
autoScroll: true,
items: Testopia.TestCaseTextEditor('effect', data)
}
}],
buttons: actionResultsButtons
};
};
Testopia.TestCaseRun.Info = function(){
this.caserun_id;
this.store = new Ext.data.Store({
url: 'tr_caserun.cgi',
baseParams: {
action: 'gettext'
},
reader: new Ext.data.XmlReader({
record: 'casetext',
id: 'case_id'
}, [{
name: 'action',
mapping: 'action'
}, {
name: 'results',
mapping: 'effect'
}, {
name: 'setup',
mapping: 'setup'
}, {
name: 'breakdown',
mapping: 'breakdown'
}, {
name: 'case_id',
mapping: 'case_id'
}, {
name: 'summary',
mapping: 'summary'
}, {
name: 'notes',
mapping: 'notes'
}])
});
var store = this.store;
store.on('load', function(s, r)
{
if (Param_Use_HTMLEditor)
{
Ext.getCmp('action_editor').setValue(r[0].get('action'));
Ext.getCmp('effect_editor').setValue(r[0].get('results'));
if (Param_Show_Setup_Breakdown)
{
Ext.getCmp('setup_editor').setValue(r[0].get('setup'));
Ext.getCmp('breakdown_editor').setValue(r[0].get('breakdown'));
}
}
else
{
Ext.getCmp('action_editor').body.update(r[0].get('action'));
Ext.getCmp('action_textarea').setValue(r[0].get('action'));
Ext.getCmp('effect_editor').body.update(r[0].get('results'));
Ext.getCmp('effect_textarea').setValue(r[0].get('results'));
if (Param_Show_Setup_Breakdown)
{
Ext.getCmp('setup_editor').body.update(r[0].get('setup'));
Ext.getCmp('effect_textarea').setValue(r[0].get('setup'));
Ext.getCmp('breakdown_editor').body.update(r[0].get('breakdown'));
Ext.getCmp('breakdown_textarea').setValue(r[0].get('breakdown'));
}
}
if (!r[0].get('results').match(/^\s*(<[^>]*>\s*)*$/))
Ext.getCmp('showhide_results_btn').handler();
Ext.getCmp('caserun_tb_summary').setText('Case ' + r[0].get('case_id') + ' - ' + r[0].get('summary'));
});
appendNote = function(){
var form = new Ext.form.BasicForm('testopia_helper_frm', {});
form.submit({
url: 'tr_list_caseruns.cgi',
params: {
action: 'update',
note: Ext.getCmp('caserun_append_note_fld').getValue(),
ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id')
},
success: function(){
Ext.getCmp('caserun_append_note_fld').reset();
store.reload();
},
failure: Testopia.Util.error
});
};
var summary_tb = new Ext.Toolbar({
id: 'summary_tb',
disabled: true,
items: [new Ext.Button({
template: imgButtonTpl,
text: 'extensions/testopia/img/IDLE.gif',
tooltip: 'Mark as IDLE (Not Run)',
handler: function(){
Testopia.Util.updateFromList('caserun', {
status_id: 1,
ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id')
}, Ext.getCmp('caserun_grid'));
}
}), new Ext.Button({
template: imgButtonTpl,
text: 'extensions/testopia/img/PASSED.gif',
tooltip: 'Mark as PASSED',
handler: function(){
Testopia.Util.updateFromList('caserun', {
status_id: 2,
ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id'),
update_bug: Ext.getCmp('update_bugs').getValue()
}, Ext.getCmp('caserun_grid'));
}
}), new Ext.Button({
template: imgButtonTpl,
text: 'extensions/testopia/img/FAILED.gif',
tooltip: 'Mark as FAILED',
handler: function(){
Testopia.Util.updateFromList('caserun', {
status_id: 3,
ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id'),
update_bug: Ext.getCmp('update_bugs').getValue()
}, Ext.getCmp('caserun_grid'));
}
}), new Ext.Button({
template: imgButtonTpl,
text: 'extensions/testopia/img/RUNNING.gif',
tooltip: 'Mark as RUNNING',
handler: function(){
var reassign = 0;
var isowner = 1;
var sel = Ext.getCmp('caserun_grid').getSelectionModel().getSelections();
for (var i = 0; i < sel.length; i++) {
if (sel[i].get('assignee') != user_login) {
isowner = 0;
break;
}
}
if (isowner == 0) {
Ext.Msg.show({
title: "Reassign Test Case?",
msg: 'Setting this test case to Running will lock it so that only the assignee can update it. Would you like to make yourself the assignee?',
buttons: Ext.MessageBox.YESNO,
icon: Ext.MessageBox.QUESTION,
fn: function(btn){
if (btn == 'yes') {
reassign = 1;
}
Testopia.Util.updateFromList('caserun', {
status_id: 4,
reassign: reassign,
ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id')
}, Ext.getCmp('caserun_grid'));
}
});
}
else {
Testopia.Util.updateFromList('caserun', {
status_id: 4,
reassign: reassign,
ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id')
}, Ext.getCmp('caserun_grid'));
}
}
}), new Ext.Button({
template: imgButtonTpl,
text: 'extensions/testopia/img/PAUSED.gif',
tooltip: 'Mark as PAUSED',
handler: function(){
Testopia.Util.updateFromList('caserun', {
status_id: 5,
ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id')
}, Ext.getCmp('caserun_grid'));
}
}), new Ext.Button({
template: imgButtonTpl,
text: 'extensions/testopia/img/BLOCKED.gif',
tooltip: 'Mark as BLOCKED',
handler: function(){
Testopia.Util.updateFromList('caserun', {
status_id: 6,
ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id')
}, Ext.getCmp('caserun_grid'));
}
}), new Ext.Button({
template: imgButtonTpl,
text: 'extensions/testopia/img/ERROR.gif',
tooltip: 'Mark as ERROR',
handler: function(){
Testopia.Util.updateFromList('caserun', {
status_id: 7,
ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id')
}, Ext.getCmp('caserun_grid'));
}
}), new Ext.Toolbar.TextItem({text:'', id:'caserun_tb_summary'})]
});
Testopia.TestCaseUpdateText = function() {
Testopia.TestCaseUpdateTextForId(Ext.getCmp('caserun_grid').getSelectionModel().getSelected().get('case_id'));
};
Testopia.TestCaseRun.Info.superclass.constructor.call(this, {
id: 'case_details_panel',
layout: 'fit',
region: 'north',
split: true,
border: false,
style: 'padding-bottom: 10px',
bodyBorder: false,
collapsible: true,
height: 340,
items: [{
xtype: 'tabpanel',
bodyBorder: false,
activeTab: 0,
id: 'caserun_center_region',
title: 'Details',
tbar: summary_tb,
items: [
Testopia.TestCaseActionPanel(),
{
title: 'Notes',
id: 'caserun_notes_panel',
border: false,
bodyBorder: false,
autoScroll: true,
layout: 'fit',
items: [{
xtype: 'dataview',
bodyBorder: false,
store: store,
itemSelector: 'div.breakdowndiv',
loadingText: 'Loading...',
tpl: new Ext.XTemplate('<tpl for=".">', '<div id="notesdiv" style="margin: 5px; padding: 5px; border: 1px solid black;"><pre>{notes}</pre></div>', '</tpl>', '<div class="x-clear"><input id="caserun_append_note_fld" ></div>')
}],
bbar: ['Add a Note: ', {
xtype: 'textfield',
id: 'caserun_append_note_fld',
listeners: {'afterrender': function(){
this.setWidth(Ext.getCmp('caserun_notes_panel').container.getWidth() - 150)
}},
width: 650
}, {
xtype: 'button',
text: 'Append Note',
handler: appendNote.createDelegate(this)
}]
},
new Testopia.TestCaseRun.History(),
new Testopia.Attachment.Grid({id: 0, type: 'caserun'}),
new Testopia.TestCase.Bugs.Grid(),
new Testopia.TestCase.Components(),
new Testopia.Tags.ObjectTags('case', 0)
]}]
});
if (Param_Show_Setup_Breakdown)
{
Ext.getCmp('caserun_center_region').add(Testopia.TestCaseSetupBreakdownPanel());
Ext.getCmp('caserun_center_region').doLayout();
}
};
Ext.extend(Testopia.TestCaseRun.Info, Ext.Panel, this);
Testopia.TestCaseRun.History = function(){
this.store = new Ext.data.JsonStore({
url: 'tr_caserun.cgi',
listeners: { 'exception': Testopia.Util.loadError },
baseParams: {
action: 'gethistory'
},
root: 'records',
fields: [{
name: 'caserun_id',
mapping: 'case_run_id'
}, {
name: 'build',
mapping: 'build_name'
}, {
name: 'environment',
mapping: 'env_name'
}, {
name: 'status',
mapping: 'status_name'
}, {
name: 'testedby',
mapping: 'testedby'
}, {
name: 'closed',
mapping: 'close_date'
}, {
name: 'isactive',
mapping: 'isactive'
}, {
name: "bug_list",
mapping: "bug_list"
}]
});
this.columns = [{
header: "Build",
width: 150,
dataIndex: 'build',
sortable: true
}, {
header: "Environment",
width: 150,
dataIndex: 'environment',
sortable: true
}, {
header: "Status",
width: 50,
dataIndex: 'status',
sortable: true,
renderer: Testopia.Util.displayStatusIcon
}, {
header: "Tested By",
width: 200,
dataIndex: 'testedby',
sortable: true
}, {
header: "Closed",
width: 150,
dataIndex: 'closed',
sortable: true
}, {
header: "Bugs In This Build and Environment",
width: 100,
dataIndex: "bug_list",
sortable: false,
hideable: true,
renderer: function(v){
if (!v) {
return;
}
var bugs = v.bugs;
var rets = '';
for (var i = 0; i < bugs.length; i++) {
if (typeof bugs[i] != 'function') {
rets = rets + '<a href="show_bug.cgi?id=' + bugs[i].bug_id + '" ' + (bugs[i].closed ? 'class="bz_closed"' : '') + '>' + bugs[i].bug_id + '</a>, ';
}
}
return rets;
}
}];
Testopia.TestCaseRun.History.superclass.constructor.call(this, {
border: false,
title: 'History',
id: 'caserun_history_panel',
bodyBorder: false,
loadMask: {
msg: 'Loading Test Cases...'
},
autoScroll: true,
sm: new Ext.grid.RowSelectionModel({
singleSelect: true
})
});
this.on('activate', this.onActivate, this);
};
Ext.extend(Testopia.TestCaseRun.History, Ext.grid.GridPanel, {
onActivate: function(event){
this.store.load({
params: {
action: 'gethistory',
caserun_id: Ext.getCmp('caserun_grid').getSelectionModel().getSelected().get('caserun_id')
}
});
}
});
Testopia.TestCase.Bugs.Grid = function(id){
var testopia_form = new Ext.form.BasicForm('testopia_helper_frm', {});
function bug_link(id){
return '<a href="show_bug.cgi?id=' + id + '" target="_blank">' + id + '</a>';
}
var tcid;
if (id) {
tcid = id;
}
this.tcid = tcid;
this.store = new Ext.data.JsonStore({
url: 'tr_process_case.cgi',
root: 'bugs',
listeners: { 'exception': Testopia.Util.loadError },
baseParams: {
action: 'getbugs'
},
fields: [{
name: 'run_id',
mapping: 'run_id'
}, {
name: 'build',
mapping: 'build'
}, {
name: 'env',
mapping: 'env'
}, {
name: 'summary',
mapping: 'summary'
}, {
name: 'case_run_id',
mapping: 'case_run_id'
}, {
name: 'bug_id',
mapping: 'bug_id'
}, {
name: 'status',
mapping: 'status'
}, {
name: 'resolution',
mapping: 'resolution'
}, {
name: 'assignee',
mapping: 'assignee'
}, {
name: 'severity',
mapping: 'severity'
}, {
name: 'priority',
mapping: 'priority'
}]
});
addbug = function(){
tcid = this.tcid;
var ids;
var type = 'case';
if (Ext.getCmp('caserun_grid')) {
type = 'caserun';
ids = Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id');
}
else {
ids = tcid;
}
testopia_form.submit({
url: 'tr_list_cases.cgi',
params: {
action: 'update_bugs',
bug_action: 'attach',
bugs: Ext.getCmp('attachbug').getValue(),
type: type,
ids: ids
},
success: function(){
ds.load({
params: {
case_id: tcid
}
});
Ext.getCmp('attachbug').reset();
},
failure: Testopia.Util.error
});
};
removebug = function(){
tcid = this.tcid;
var type = 'case';
if (Ext.getCmp('caserun_grid')) {
type = 'caserun';
ids = Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id');
}
else {
ids = tcid;
}
testopia_form.submit({
url: 'tr_list_cases.cgi',
params: {
action: 'update_bugs',
bugs: Testopia.Util.getSelectedObjects(Ext.getCmp('case_bugs_panel'), 'bug_id'),
type: type,
ids: ids
},
success: function(){
ds.load({
params: {
case_id: tcid
}
});
},
failure: Testopia.Util.error
});
};
newbug = function(){
var bug_panel = new Ext.Panel({
id: 'new_bug_panel'
});
var caserun_id;
if (Ext.getCmp('caserun_grid') && Ext.getCmp('caserun_grid').getSelectionModel().getCount()) {
caserun_id = Ext.getCmp('caserun_grid').getSelectionModel().getSelected().get('caserun_id');
}
var store = new Ext.data.Store({
url: 'tr_process_case.cgi',
baseParams: {
action: 'case_to_bug',
case_id: this.tcid,
caserun_id: caserun_id
},
reader: new Ext.data.XmlReader({
record: 'newbug',
id: 'case_id'
}, [{
name: 'product',
mapping: 'product'
}, {
name: 'version',
mapping: 'version'
}, {
name: 'component',
mapping: 'component'
}, {
name: 'comment',
mapping: 'comment'
}, {
name: 'case_id',
mapping: 'case_id'
}, {
name: 'assigned_to',
mapping: 'assigned_to'
}, {
name: 'qa_contact',
mapping: 'qa_contact'
}, {
name: 'short_desc',
mapping: 'short_desc'
}])
});
store.load();
store.on('load', function(){
var url = 'enter_bug.cgi?';
for (var i=0; i<store.fields.keys.length; i++){
url = url + store.fields.keys[i] + '=' + encodeURI(store.getAt(0).get(store.fields.keys[i])) + '&';
}
url = url + 'caserun_id=' + caserun_id;
window.open(url);
});
};
var ds = this.store;
this.columns = [{
header: "Bug",
width: 150,
dataIndex: 'bug_id',
sortable: true,
renderer: bug_link
}, {
header: "Found In Run",
width: 50,
dataIndex: 'run_id',
sortable: true,
renderer: Testopia.Util.makeLink.createDelegate(this,['run'],true)
}, {
header: "With Build",
width: 50,
dataIndex: 'build',
sortable: true
}, {
header: "Environment",
width: 50,
dataIndex: 'env',
sortable: true
}, {
id: 'bugs_summary',
header: "Summary",
width: 200,
dataIndex: 'summary',
sortable: true
}, {
header: "Status",
width: 50,
dataIndex: 'status',
sortable: true
}, {
header: "Resolution",
width: 50,
dataIndex: 'resolution',
sortable: true
}, {
header: "Severity",
width: 50,
dataIndex: 'severity',
sortable: true
}, {
header: "Asignee",
width: 150,
dataIndex: 'assignee',
sortable: true
}, {
header: "Priority",
width: 50,
dataIndex: 'priority',
sortable: true
}];
Testopia.TestCase.Bugs.Grid.superclass.constructor.call(this, {
tbar: [new Ext.form.TextField({
width: 50,
id: 'attachbug'
}), {
xtype: 'button',
tooltip: "Attach a Bug",
icon: 'extensions/testopia/img/add.png',
iconCls: 'img_button_16x',
handler: addbug.createDelegate(this)
}, {
xtype: 'button',
tooltip: "File new Bug",
icon: 'extensions/testopia/img/new.png',
iconCls: 'img_button_16x',
handler: newbug.createDelegate(this)
}, {
xtype: 'button',
tooltip: "Remove selected bugs from test case or run",
icon: 'extensions/testopia/img/delete.png',
iconCls: 'img_button_16x',
handler: removebug.createDelegate(this)
}, '-', 'This view includes all bugs attached to the selected test case regardless of run'],
border: false,
title: 'Bugs',
id: 'case_bugs_panel',
bodyBorder: false,
autoExpandColumn: 'bugs_summary',
loadMask: {
msg: 'Loading...'
},
autoScroll: true,
sm: new Ext.grid.RowSelectionModel({
singleSelect: true
})
});
this.on('rowcontextmenu', this.onContextClick, this);
this.on('activate', this.onActivate, this);
};
Ext.extend(Testopia.TestCase.Bugs.Grid, Ext.grid.GridPanel, {
onContextClick: function(grid, index, e){
this.menu = new Ext.menu.Menu({
id: 'tags-ctx-menu',
items: [{
text: 'Refresh List',
icon: 'extensions/testopia/img/refresh.png',
iconCls: 'img_button_16x',
handler: function(){
grid.store.reload();
}
}, {
text: 'Attach Selected Bug to Current Run/Build/Environment',
id: 'reattach_bug',
icon: 'extensions/testopia/img/add.png',
disabled: Ext.getCmp('caserun_grid') ? false : true,
iconCls: 'img_button_16x',
handler: function(){
var r = grid.store.getAt(index);
var testopia_form = new Ext.form.BasicForm('testopia_helper_frm', {});
testopia_form.submit({
url: 'tr_list_cases.cgi',
params: {
action: 'update_bugs',
bug_action: 'attach',
bugs: Testopia.Util.getSelectedObjects(Ext.getCmp('case_bugs_panel'), 'bug_id'),
type: 'caserun',
ids: Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id')
},
success: function(){
Ext.getCmp('caserun_grid').store.reload();
grid.store.reload();
Ext.getCmp('attachbug').reset();
},
failure: Testopia.Util.error
});
}
}]
});
e.stopEvent();
if (grid.getSelectionModel().getCount() < 1) {
grid.getSelectionModel().selectRow(index);
}
this.menu.showAt(e.getXY());
},
onActivate: function(event){
this.store.load({
params: {
case_id: this.tcid
}
});
}
});
Testopia.TestCase.Components = function(id){
var testopia_form = new Ext.form.BasicForm('testopia_helper_frm', {});
var tcid;
var product_id;
if (id) {
tcid = id;
}
else {
if (Ext.getCmp('caserun_grid').getSelectionModel().getCount()) {
tcid = Ext.getCmp('caserun_grid').getSelectionModel().getSelected().get('case_id');
}
}
try {
if (run) {
product_id = run.plan.product_id;
}
} 
catch (err) {
try{
if (tcase) {
product_id = tcase.product_id;
}
}
catch (e) {}
}
this.tcid = tcid;
this.store = new Ext.data.JsonStore({
url: 'tr_process_case.cgi',
root: 'comps',
listeners: { 'exception': Testopia.Util.loadError },
baseParams: {
action: 'getcomponents'
},
id: 'component_id',
fields: [{
name: 'name',
mapping: 'name'
}, {
name: 'id',
mapping: 'id'
}, {
name: 'product',
mapping: 'product'
}]
});
var ds = this.store;
this.columns = [{
header: "ID",
width: 150,
dataIndex: 'id',
sortable: false,
hidden: true
}, {
id: 'comp_name',
header: "Component",
width: 150,
dataIndex: 'name',
sortable: true
}, {
id: 'product',
header: "Product",
width: 150,
dataIndex: 'product',
sortable: true
}];
var pchooser = new Testopia.Product.Combo({
id: 'comp_product_chooser',
mode: 'local',
value: product_id
});
var compchooser = new Testopia.TestCase.ComponentCombo({
params: {
product_id: product_id
}
});
this.pchooser = pchooser;
pchooser.on('select', function(){
compchooser.reset();
compchooser.store.baseParams = {
product_id: pchooser.getValue(),
action: 'getcomponents'
};
compchooser.store.load();
});
addcomp = function(){
tcid = this.tcid;
if (typeof tcid == 'object') {
testopia_form.submit({
url: 'tr_list_cases.cgi',
params: {
action: 'update',
comp_action: 'add',
components: compchooser.getValue(),
ids: Testopia.Util.getSelectedObjects(tcid, 'case_id')
},
success: function(){
Testopia.Util.notify.msg('Component Added', 'Added component {0} to {1} cases(s)', compchooser.getRawValue(), tcid.getSelectionModel().getCount());
},
failure: Testopia.Util.error
});
return;
}
testopia_form.submit({
url: 'tr_process_case.cgi',
params: {
action: 'addcomponent',
component_id: compchooser.getValue(),
case_id: this.tcid
},
success: function(){
ds.load({
params: {
case_id: tcid
}
});
},
failure: Testopia.Util.error
});
};
removecomp = function(){
tcid = this.tcid;
if (typeof tcid == 'object') {
testopia_form.submit({
url: 'tr_list_cases.cgi',
params: {
action: 'update',
comp_action: 'rem',
components: compchooser.getValue(),
ids: Testopia.Util.getSelectedObjects(tcid, 'case_id')
},
success: function(){
Testopia.Util.notify.msg('Component Removed', 'Removed component {0} from {1} cases(s)', compchooser.getRawValue(), tcid.getSelectionModel().getCount());
},
failure: Testopia.Util.error
});
return;
}
testopia_form.submit({
url: 'tr_process_case.cgi',
params: {
action: 'removecomponent',
component_id: Testopia.Util.getSelectedObjects(Ext.getCmp('case_comps_panel'), 'id'),
case_id: this.tcid
},
success: function(){
ds.load({
params: {
case_id: tcid
}
});
},
failure: Testopia.Util.error
});
};
Testopia.TestCase.Components.superclass.constructor.call(this, {
tbar: [pchooser, compchooser, {
xtype: 'button',
tooltip: "Attach selected component",
icon: 'extensions/testopia/img/add.png',
iconCls: 'img_button_16x',
handler: addcomp.createDelegate(this)
}, {
xtype: 'button',
tooltip: "Remove component from test case",
icon: 'extensions/testopia/img/delete.png',
iconCls: 'img_button_16x',
handler: removecomp.createDelegate(this)
}],
border: false,
title: 'Components',
id: 'case_comps_panel',
bodyBorder: false,
autoExpandColumn: 'comp_name',
loadMask: {
msg: 'Loading...'
},
autoScroll: true,
sm: new Ext.grid.RowSelectionModel({
singleSelect: false
})
});
this.on('rowcontextmenu', this.onContextClick, this);
this.on('activate', this.onActivate, this);
};
Ext.extend(Testopia.TestCase.Components, Ext.grid.GridPanel, {
onContextClick: function(grid, index, e){
if (!this.menu) { // create context menu on first right click
this.menu = new Ext.menu.Menu({
id: 'tags-ctx-menu',
items: [{
text: 'Refresh List',
icon: 'extensions/testopia/img/refresh.png',
iconCls: 'img_button_16x',
handler: function(){
grid.store.reload();
}
}]
});
}
e.stopEvent();
if (grid.getSelectionModel().getCount() < 1) {
grid.getSelectionModel().selectRow(index);
}
this.menu.showAt(e.getXY());
},
onActivate: function(event){
this.store.load({
params: {
case_id: this.tcid
},
callback: function(r, o, s){
if (s === false) {
Testopia.Util.loadError();
}
}
});
this.pchooser.store.load();
}
});
Testopia.TestCase.Bugs.update = function(grid){
function commitBug(action, value, grid){
var form = new Ext.form.BasicForm('testopia_helper_frm', {});
form.submit({
url: 'tr_list_cases.cgi',
params: {
action: 'update_bugs',
bug_action: action,
bugs: value,
type: 'case',
ids: Testopia.Util.getSelectedObjects(grid, 'case_id')
},
success: function(){
},
failure: Testopia.Util.error
});
}
var win = new Ext.Window({
title: 'Add or Remove Bugs',
id: 'bugs_edit_win',
layout: 'fit',
split: true,
plain: true,
shadow: false,
listeners: {'afterlayout':function(){Ext.getCmp('bug_field').focus('',10)}},
width: 350,
height: 150,
items: [new Ext.FormPanel({
labelWidth: '40',
bodyStyle: 'padding: 5px',
items: [{
xtype: 'textfield',
name: 'bugs',
id: 'bug_field',
fieldLabel: 'Bugs'
}]
})],
buttons: [{
text: 'Attach Bug',
handler: function(){
commitBug('attach', Ext.getCmp('bug_field').getValue(), grid);
win.close();
}
}, {
text: 'Remove Bug',
handler: function(){
commitBug('remove', Ext.getCmp('bug_field').getValue(), grid);
win.close();
}
}, {
text: 'Close',
handler: function(){
win.close();
}
}]
});
win.show();
};
Testopia.Category.Store = function(params, auto){
params.action = 'list';
Testopia.Category.Store.superclass.constructor.call(this, {
url: 'tr_categories.cgi',
root: 'categories',
listeners: { 'exception': Testopia.Util.loadError },
baseParams: params,
id: 'category_id',
autoLoad: auto,
fields: [{
name: "category_id",
mapping: "category_id"
}, {
name: "name",
mapping: "name"
}, {
name: "description",
mapping: "description"
}]
});
};
Ext.extend(Testopia.Category.Store, Ext.data.JsonStore);
Testopia.Category.Combo = function(cfg){
Testopia.Category.Combo.superclass.constructor.call(this, {
id: cfg.id || 'case_category_combo',
store: cfg.transform ? false : new Testopia.Category.Store(cfg.params, cfg.mode == 'local' ? true : false),
loadingText: 'Looking up categories...',
displayField: 'name',
valueField: 'category_id',
typeAhead: true,
triggerAction: 'all',
minListWidth: 300,
forceSelection: true,
transform: cfg.transform,
emptyText: 'Please select...'
});
Ext.apply(this, cfg);
this.store.on('load', function(){
if (cfg.value) {
this.setValue(cfg.value);
}
}, this);
};
Ext.extend(Testopia.Category.Combo, Ext.form.ComboBox);
Testopia.Category.Grid = function(product_id){
this.product_id = product_id;
this.store = new Testopia.Category.Store({}, false);
var ds = this.store;
this.columns = [{
header: "Name",
width: 120,
sortable: true,
dataIndex: 'name',
editor: {
xtype: 'textfield',
value: 'name',
allowBlank: false
} 
}, {
header: "Description",
width: 120,
id: 'category_desc_column',
editor: {
xtype: 'textfield',
value: 'description'
},
sortable: true,
dataIndex: 'description'
}];
this.form = new Ext.form.BasicForm('testopia_helper_frm', {});
Testopia.Category.Grid.superclass.constructor.call(this, {
title: 'Categories',
id: 'category_grid',
loadMask: {
msg: 'Loading Categories...'
},
autoExpandColumn: "category_desc_column",
autoScroll: true,
plugins: [new Ext.ux.grid.RowEditor({
id:'category_row_editor',
saveText: 'Update'
})],
enableColumnHide: true,
sm: new Ext.grid.RowSelectionModel({
singleSelect: true
}),
viewConfig: {
forceFit: true
},        
tbar: [new Ext.Toolbar.Fill(), {
xtype: 'button',
id: 'edit_category_btn',
icon: 'extensions/testopia/img/edit.png',
iconCls: 'img_button_16x',
tooltip: 'Edit Selected Category',
handler: function(){
Testopia.Util.editFirstSelection(Ext.getCmp('category_grid'));
}
}, {
xtype: 'button',
id: 'add_category_btn',
icon: 'extensions/testopia/img/add.png',
iconCls: 'img_button_16x',
tooltip: 'Add a new Category',
handler: this.newRecord
}, {
xtype: 'button',
icon: 'extensions/testopia/img/delete.png',
iconCls: 'img_button_16x',
tooltip: 'Delete this Category',
handler: function(){
var m = Ext.getCmp('category_grid').getSelectionModel().getSelected();
if (!m) {
Ext.MessageBox.alert('Message', 'Please select at least one Category to delete');
}
else {
Testopia.Category.remove(product_id);
}
}
}]
});
this.on('rowcontextmenu', this.onContextClick, this);
this.on('activate', this.onActivate, this);
Ext.getCmp('category_row_editor').on('afteredit', this.onGridEdit, this);
};
Ext.extend(Testopia.Category.Grid, Ext.grid.GridPanel, {
newRecord: function(){
NewCategory = Ext.data.Record.create([{
name: 'name',
type: 'string'
}, {
name: 'description',
type: 'string'
}]);
var b = new NewCategory({
name: '',
description: ''
});
var g = Ext.getCmp('category_grid');
g.store.insert(0, b);
Ext.getCmp('category_row_editor').startEditing(0);
},
onContextClick: function(grid, index, e){
grid.getSelectionModel().selectRow(index);
if (!this.menu) { // create context menu on first right click
this.menu = new Ext.menu.Menu({
id: 'category-ctx-menu',
enableScrolling: false,
items: [{
text: 'Add a Category', 
icon: 'extensions/testopia/img/add.png',
iconCls: 'img_button_16x',
handler: this.newRecord
}, {
text: 'Edit This Category', 
icon: 'extensions/testopia/img/edit.png',
iconCls: 'img_button_16x',
handler: function(){
Testopia.Util.editFirstSelection(grid);
}
}, {
text: 'Refresh',
icon: 'extensions/testopia/img/refresh.png',
iconCls: 'img_button_16x',
handler: function(){
grid.store.reload();
} 
}]
});
}
e.stopEvent();
this.menu.showAt(e.getXY());
},
onGridEdit: function(e){
var myparams = e.record.data;
var ds = this.store;
myparams.product_id = this.product_id;
if (myparams.build_id) {
myparams.action = "edit";
}
else {
myparams.action = "add";
}
this.form.submit({
url: "tr_categories.cgi",
params: myparams,
success: function(f, a){
if (a.result.category_id) {
e.record.set('category_id', a.result.category_id);
}
ds.commitChanges();
},
failure: function(f, a){
Testopia.Util.error(f, a);
ds.rejectChanges();
}
});
},
onActivate: function(event){
if (!this.product_id) {
Ext.Msg.alert('Error', 'Please select a product.');
Ext.getCmp('edit_category_btn').disable();
Ext.getCmp('add_category_btn').disable();
return;
}
else {
if (!this.store.getCount()) {
this.store.load({
params: {
product_id: this.product_id
}
});
}
}
}
});
Testopia.Category.remove = function(){
if (!Ext.getCmp('category_grid').getSelectionModel().getSelected().get('category_id')) {
Ext.getCmp('category_grid').store.reload();
return;
}
Ext.Msg.show({
title: 'Confirm Delete?',
msg: CASE_CATEGORY_DELETE_WARNING,
buttons: Ext.Msg.YESNO,
animEl: 'casecategory-delete-btn',
icon: Ext.MessageBox.QUESTION,
fn: function(btn){
if (btn == 'yes') {
var testopia_form = new Ext.form.BasicForm('testopia_helper_frm');
testopia_form.submit({
url: 'tr_categories.cgi',
params: {
category_id: Ext.getCmp('category_grid').getSelectionModel().getSelected().get('category_id'),
action: 'delete',
product_id: Ext.getCmp('category_grid').product_id
},
success: function(data){
Ext.Msg.show({
msg: "Test case category deleted",
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.INFO
});
Ext.getCmp('category_grid').store.reload();
},
failure: Testopia.Util.error
});
}
}
});
};
Ext.ux.TabCloseMenu = function(){
var tabs, menu, ctxItem;
this.init = function(tp){
tabs = tp;
tabs.on('contextmenu', onContextMenu);
}
function onContextMenu(ts, item, e){
if(!menu){ // create context menu on first right click
menu = new Ext.menu.Menu([{
id: tabs.id + '-close',
text: 'Close Tab',
handler : function(){
tabs.remove(ctxItem);
}
},{
id: tabs.id + '-close-others',
text: 'Close Other Tabs',
handler : function(){
tabs.items.each(function(item){
if(item.closable && item != ctxItem){
tabs.remove(item);
}
});
}
}]);
}
ctxItem = item;
var items = menu.items;
items.get(tabs.id + '-close').setDisabled(!item.closable);
var disableOthers = true;
tabs.items.each(function(){
if(this != item && this.closable){
disableOthers = false;
return false;
}
});
items.get(tabs.id + '-close-others').setDisabled(disableOthers);
menu.showAt(e.getPoint());
}
};
diff_tab_panel = function(type, id, doctype){
var self = this;
var doc_store = new Ext.data.JsonStore({
url: "tr_history.cgi",
listeners: { 'exception': Testopia.Util.loadError },
baseParams: {action: 'getversions',
type:   type,
id:     id},
root: 'versions',
fields: [
{name: 'name', mapping: 'name',
name: 'id', mapping: 'id'}
]
})
diff_tab_panel.superclass.constructor.call(this, {
title:  'Test Panel',
height: 500,
resizeTabs:true, // turn on tab resizing
minTabWidth: 115,
tabWidth:135,
enableTabScroll:true,
defaults: {autoScroll:true},
plugins: new Ext.ux.TabCloseMenu(),
activeTab: 0,
tbar: [  
new Ext.form.ComboBox({
displayField: 'name',
valueField: 'id',
name: 'product',
id: 'product_combo',
fieldLabel: "Product",
store: doc_store,
emptyText: 'Select a version...',
width: 200
}),
" Right: ",
new Ext.Toolbar.Spacer(),                       
new Ext.form.ComboBox({
}),
" HTML: ",
new Ext.form.Radio({
id:    'format',
value: 'html',
checked: true
}),
" Raw: ",
new Ext.form.Radio({
id:    'format',
value: 'raw'
}),                                   
new Ext.Button({
text:    'Diff',
handler: addTab
}),
new Ext.Toolbar.Separator(),                             
"Show Version: ",
new Ext.form.ComboBox({
}),                             
new Ext.Button({
text:    'Show',
handler: addTab
})
]
});
function addTab() {
self.add({
title:   'New Tab ',
iconCls: 'tabs',
html:    'diff_text',
closable:true
}).show();
}                                  
}
Ext.extend(diff_tab_panel, Ext.TabPanel);
Testopia.Environment.Store = function(params, auto){
params.ctype = 'json';
Testopia.Environment.Store.superclass.constructor.call(this, {
url: 'tr_list_environments.cgi',
listeners: {
'exception': Testopia.Util.loadError
},
root: 'Result',
baseParams: params,
totalProperty: 'totalResultsAvailable',
autoLoad: auto,
id: 'environment_id',
fields: [{
name: "environment_id",
mapping: "environment_id"
}, {
name: "name",
mapping: "name"
}, {
name: "run_count",
mapping: "run_count"
}, {
name: "isactive",
mapping: "isactive"
}, {
name: "product",
mapping: "product_name"
}],
remoteSort: true
});
this.paramNames.sort = "order";
};
Ext.extend(Testopia.Environment.Store, Ext.data.JsonStore);
Testopia.Environment.Combo = function(cfg){
if (cfg.params) {
cfg.params.viewall = 1;
}
Testopia.Environment.Combo.superclass.constructor.call(this, {
id: cfg.id || 'environment_combo',
store: cfg.transform ? false : new Testopia.Environment.Store(cfg.params, cfg.mode == 'local' ? true : false),
loadingText: 'Looking up environments...',
displayField: 'name',
valueField: 'environment_id',
typeAhead: true,
triggerAction: 'all',
minListWidth: 300,
forceSelection: true,
transform: cfg.transform,
emptyText: 'Environments...'
});
Ext.apply(this, cfg);
this.store.on('load', function(){
if (cfg.value) {
this.setValue(cfg.value);
}
}, this);
};
Ext.extend(Testopia.Environment.Combo, Ext.form.ComboBox);
Testopia.Environment.Grid = function(params, cfg){
this.params = params;
this.product_id = params.product_id;
function environmentLink(id){
return '<a href="tr_environments.cgi?env_id=' + id + '">' + id + '</a>';
}
function productLink(id){
return '<a href="tr_show_product.cgi?product_id=' + id + '">' + id + '</a>';
}
this.store = new Testopia.Environment.Store(params, false);
var ds = this.store;
this.columns = [{
header: "ID",
width: 30,
dataIndex: "environment_id",
sortable: true,
renderer: environmentLink,
hideable: false
}, {
header: "Environment Name",
width: 110,
dataIndex: "name",
id: 'env_name_col',
sortable: true,
editor: new Ext.grid.GridEditor(new Ext.form.TextField({
allowBlank: false
}), {
id: 'env_name_edt'
})
}, {
header: "Product Name",
width: 150,
dataIndex: "product",
sortable: true,
hidden: true
}, {
header: "Run Count",
width: 30,
dataIndex: "run_count",
sortable: false
}, new Ext.grid.CheckColumn({
sortable: true,
header: 'Active',
dataIndex: 'isactive',
editor: new Ext.grid.GridEditor(new Ext.form.Checkbox({
value: 'isactive'
})),
width: 25
})];
this.form = new Ext.form.BasicForm('testopia_helper_frm', {});
this.bbar = new Testopia.Util.PagingBar('environment', this.store);
Testopia.Environment.Grid.superclass.constructor.call(this, {
title: 'Environments',
id: 'environment-grid',
loadMask: {
msg: 'Loading Environments...'
},
autoExpandColumn: "env_name_col",
autoScroll: true,
plugins: [new Ext.ux.grid.RowEditor({
saveText: 'Update'
})],
sm: new Ext.grid.RowSelectionModel({
singleSelect: true,
listeners: {
'rowselect': function(sm, i, r){
Ext.getCmp('delete_env_list_btn').enable();
Ext.getCmp('clone_env_list_btn').enable();
},
'rowdeselect': function(sm, i, r){
if (sm.getCount() < 1) {
Ext.getCmp('delete_env_list_btn').disable();
Ext.getCmp('clone_env_list_btn').disable();
}
}
}
}),
viewConfig: {
forceFit: true
},
tbar: [{
xtype: 'button',
text: 'Import',
handler: this.importEnv.createDelegate(this)
}, new Ext.Toolbar.Fill(), {
xtype: 'button',
id: 'add_env_list_btn',
icon: 'extensions/testopia/img/add.png',
iconCls: 'img_button_16x',
tooltip: 'Add an Environment',
handler: this.createEnv.createDelegate(this, ['', 'add'])
}, {
xtype: 'button',
id: 'clone_env_list_btn',
disabled: true,
icon: 'extensions/testopia/img/copy.png',
iconCls: 'img_button_16x',
tooltip: 'Clone this Environment',
handler: this.cloneEnv.createDelegate(this)
}, {
xtype: 'button',
id: 'delete_env_list_btn',
disabled: true,
icon: 'extensions/testopia/img/delete.png',
iconCls: 'img_button_16x',
tooltip: 'Delete this Environment',
handler: this.deleteEnv.createDelegate(this)
}]
});
Ext.apply(this, cfg);
this.on('rowcontextmenu', this.onContextClick, this);
this.on('afteredit', this.onGridEdit, this);
this.on('activate', this.onActivate, this);
};
Ext.extend(Testopia.Environment.Grid, Ext.grid.EditorGridPanel, {
onContextClick: function(grid, index, e){
if (!this.menu) { // create context menu on first right click
this.menu = new Ext.menu.Menu({
enableScrolling: false,
id: 'run-ctx-menu',
items: [{
text: 'Create a new environment',
handler: function(){
window.location = "tr_new_environment.cgi";
} 
}, {
text: 'Delete Environments',
handler: this.deleteEnv.createDelegate(this)
}, {
text: 'Refresh List', 
icon: 'extensions/testopia/img/refresh.png',
iconCls: 'img_button_16x',
handler: function(){
grid.store.reload();
}
}]
});
}
e.stopEvent();
if (grid.getSelectionModel().getCount() < 1) {
grid.getSelectionModel().selectRow(index);
}
this.menu.showAt(e.getXY());
},
onGridEdit: function(e){
var myparams = {
env_id: e.record.get('environment_id')
};
var ds = this.store;
switch (e.field) {
case 'name':
myparams.action = 'rename';
myparams.name = e.value; 
break;
case 'isactive':
myparams.action = 'toggle';
break;
}
this.form.submit({
url: "tr_environments.cgi",
params: myparams,
success: function(f, a){
ds.commitChanges();
},
failure: function(f, a){
Testopia.Util.error(f, a);
ds.rejectChanges();
}
});
},
deleteEnv: function(){
var grid = this;
Ext.Msg.show({
title: 'Confirm Delete?',
msg: ENVIRONMENT_DELETE_WARNING,
buttons: Ext.Msg.YESNO,
animEl: 'case-delete-btn',
icon: Ext.MessageBox.QUESTION,
fn: function(btn){
if (btn == 'yes') {
form = new Ext.form.BasicForm('testopia_helper_frm', {});
form.submit({
url: 'tr_environments.cgi',
params: {
env_id: grid.getSelectionModel().getSelected().get('environment_id'),
action: 'delete'
},
success: function(){
Ext.Msg.show({
msg: "Test environment deleted",
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.INFO
});
grid.store.reload();
},
failure: function(f, a){
Testopia.Util.error(f, a);
grid.store.reload();
}
});
}
}
});
},
createEnv: function(name, action, id){
var grid = this;
action = action || 'add';
var win = new Ext.Window({
id: 'create-env-win',
title: 'Environment XML Import',
closable: true,
width: 400,
height: 230,
plain: true,
shadow: false,
layout: 'fit',
items: [{
xtype: 'form',
url: 'tr_environments.cgi',
bodyStyle: 'padding: 10px',
id: 'env_create_frm',
items: [{
xtype: 'field',
fieldLabel: 'Name',
inputType: 'text',
name: 'name',
value: name != '' ? 'Copy of ' + name : '',
allowBlank: false
}, new Testopia.Product.Combo({
mode: 'local',
fieldLabel: 'Product',
value: grid.product_id,
hiddenName: 'product_id'
}), {
xtype: 'hidden',
name: 'action',
value: action
}, {
xtype: 'hidden',
name: 'env_id',
value: id
}],
buttons: [{
text: 'Create',
handler: function(){
Ext.getCmp('env_create_frm').getForm().submit({
success: function(form, data){
Ext.Msg.show({
title: 'Test Environment Created',
msg: 'Test environment ' + data.result.id + ' Created. Would you like to go there now?',
buttons: Ext.Msg.YESNO,
icon: Ext.MessageBox.QUESTION,
fn: function(btn){
if (btn == 'yes') {
window.location = 'tr_environments.cgi?env_id=' + data.result.id;
}
else {
grid.store.reload();
}
}
});
Ext.getCmp('create-env-win').close();
},
failure: Testopia.Util.error
});
}
}, {
text: 'Cancel',
handler: function(){
Ext.getCmp('create-env-win').close();
}
}]
}]
});
win.show(this);
},
cloneEnv: function(){
this.createEnv(this.getSelectionModel().getSelected().get('name'), 'clone', this.getSelectionModel().getSelected().get('environment_id'));
},
importEnv: function(){
grid = this;
var win = new Ext.Window({
id: 'import-env-win',
title: 'Environment XML Import',
closable: true,
width: 400,
height: 130,
plain: true,
shadow: false,
layout: 'fit',
items: [{
xtype: 'form',
url: 'tr_import_environment.cgi',
bodyStyle: 'padding: 10px',
id: 'env_xml_import_frm',
fileUpload: true,
items: [{
xtype: 'field',
fieldLabel: 'XML',
inputType: 'file',
name: 'xml',
allowBlank: false
}],
buttons: [{
text: 'Import',
handler: function(){
Ext.getCmp('env_xml_import_frm').getForm().submit();
Ext.getCmp('import-env-win').close();
grid.store.reload();
}
}, {
text: 'Cancel',
handler: function(){
Ext.getCmp('import-env-win').close();
}
}]
}]
});
win.show(this);
},
onActivate: function(event){
if (!this.store.getCount()) {
this.store.load();
}
}
});
Testopia.TestPlan.Store = function(params, auto){
params.ctype = 'json';
Testopia.TestPlan.Store.superclass.constructor.call(this, {
url: 'tr_list_plans.cgi',
listeners: { 'exception': Testopia.Util.loadError },
baseParams: params,
totalProperty: 'totalResultsAvailable',
root: 'Result',
autoLoad: auto,
id: 'plan_id',
fields: [{
name: "plan_id",
mapping: "plan_id"
}, {
name: "name",
mapping: "name"
}, {
name: "author",
mapping: "author_name"
}, {
name: "creation_date",
mapping: "creation_date"
}, {
name: "product",
mapping: "product_name"
}, {
name: "product_id",
mapping: "product_id"
}, {
name: "prod_version",
mapping: "default_product_version"
}, {
name: "type",
mapping: "plan_type"
}, {
name: "case_count",
mapping: "case_count"
}, {
name: "run_count",
mapping: "run_count"
}],
remoteSort: true
});
this.paramNames.sort = "order";
};
Ext.extend(Testopia.TestPlan.Store, Ext.data.JsonStore);
Testopia.TestPlan.TypesStore = function(auto){
Testopia.TestPlan.TypesStore.superclass.constructor.call(this, {
url: 'tr_quicksearch.cgi',
root: 'types',
listeners: { 'exception': Testopia.Util.loadError },
baseParams: {
action: 'getplantypes'
},
autoLoad: auto,
id: 'id',
fields: [{
name: 'id',
mapping: 'id'
}, {
name: 'name',
mapping: 'name'
}]
});
};
Ext.extend(Testopia.TestPlan.TypesStore, Ext.data.JsonStore);
Testopia.TestPlan.TypesCombo = function(cfg){
Testopia.TestPlan.TypesCombo.superclass.constructor.call(this, {
id: cfg.id || 'plan_type_combo',
store: cfg.transform ? false : new Testopia.TestPlan.TypesStore(cfg.mode == 'local' ? true : false),
loadingText: 'Looking up types...',
displayField: 'name',
valueField: 'id',
typeAhead: true,
triggerAction: 'all',
minListWidth: 300,
forceSelection: true,
transform: cfg.transform,
emptyText: 'Please select...'
});
Ext.apply(this, cfg);
this.store.on('load', function(){
if (cfg.value) {
this.setValue(cfg.value);
}
}, this);
};
Ext.extend(Testopia.TestPlan.TypesCombo, Ext.form.ComboBox);
Testopia.TestPlan.Import = function(params){
var win = new Ext.Window({
id: 'plan_import_win',
closable: true,
width: 450,
height: 150,
plain: true,
shadow: false,
layout: 'fit',
items: [{
xtype: 'form',
height: 250,
url: 'tr_importer.cgi',
id: 'importform',
baseParams: {
action: 'upload',
ctype: 'json',
plan_id: params.plan_id,
product_id: params.product_id
},
fileUpload: true,
items: [{
height: 50,
style: "padding: 5px",
border: false,
html: params.product_id ? PRODUCT_PLAN_IMPORT : PLAN_CASES_IMPORT
}, {
xtype: 'field',
fieldLabel: 'Upload File',
labelStyle: "padding: 5px",
inputType: 'file',
name: 'data',
width: 300
}],
buttons: [{
text: 'Submit',
handler: function(){
Ext.getCmp('importform').getForm().submit({
success: function(){
if (params.product_id) {
Ext.getCmp('object_panel').activate('product_plan_grid');
Ext.getCmp('product_plan_grid').store.load();
}
else {
Ext.getCmp('object_panel').activate('plan_case_grid');
Ext.getCmp('plan_case_grid').store.load();
}
Ext.getCmp('plan_import_win').close();
},
failure: Testopia.Util.error
});
}
}]
}]
});
win.show(this);
}
Testopia.TestPlan.Grid = function(params, cfg){
params.limit = Ext.state.Manager.get('TESTOPIA_DEFAULT_PAGE_SIZE', 25);
params.current_tab = 'plan';
this.params = params;
var versionbox = new Testopia.Product.VersionCombo({
id: 'plan_grid_version_chooser',
hiddenName: 'prod_version',
mode: 'remote',
params: {
product_id: params.product_id
},
listeners: {
'startedit': function(){
var pid = Ext.getCmp(cfg.id || 'plan_grid').getSelectionModel().getSelected().get('product_id');
if (versionbox.store.baseParams.product_id != pid) {
versionbox.store.baseParams.product_id = pid;
versionbox.store.load();
}
}
}
});
this.store = new Testopia.TestPlan.Store(params);
var ds = this.store;
this.columns = [{
header: "ID",
width: 30,
dataIndex: 'plan_id',
sortable: true,
renderer: Testopia.Util.makeLink.createDelegate(this,['plan'],true),
hideable: false
}, {
header: "Name",
width: 220, 
dataIndex: 'name', 
id: "plan_name", 
sortable: true,
editor: {
xtype: 'textfield',
allowBlank: false
}
}, {
header: "Author",
width: 150,
sortable: true,
dataIndex: 'author'
}, {
header: "Created",
width: 110,
sortable: true,
dataIndex: 'creation_date',
hidden: true
}, {
header: "Product",
width: 180,
sortable: true,
dataIndex: 'product',
hidden: true
}, {
header: "Product Version",
width: 60,
sortable: true,
dataIndex: 'prod_version',
editor: versionbox,
renderer: Testopia.Util.ComboRenderer.createDelegate(this)
}, {
header: "Type",
width: 60,
sortable: true,
dataIndex: 'type',
editor: new Testopia.TestPlan.TypesCombo({
id: 'plan_grid_ types_chooser',
hiddenName: 'type',
mode: 'remote'
}),
renderer: Testopia.Util.ComboRenderer.createDelegate(this)
}, {
header: "Cases",
width: 20,
sortable: false,
dataIndex: 'case_count'
}, {
header: "Runs",
width: 20,
sortable: false,
dataIndex: 'run_count'
}];
this.form = new Ext.form.BasicForm('testopia_helper_frm', {});
this.bbar = new Testopia.Util.PagingBar('plan', this.store);
Testopia.TestPlan.Grid.superclass.constructor.call(this, {
title: 'Test Plans',
id: cfg.id || 'plan_grid',
layout: 'fit',
region: 'center',
stripeRows: true,
loadMask: {
msg: 'Loading Test Plans...'
},
autoExpandColumn: "plan_name",
autoScroll: true,
plugins: [new Ext.ux.grid.RowEditor({
id:'plan_row_editor',
saveText: 'Update'
})],
sm: new Ext.grid.RowSelectionModel({
singleSelect: cfg.single || false,
listeners: {
'rowselect': function(sm, i, r){
if (Ext.getCmp('plan_add_run_mnu')) {
Ext.getCmp('plan_add_run_mnu').enable();
}
if (Ext.getCmp('plan_add_case_mnu')) {
Ext.getCmp('plan_add_case_mnu').enable();
}
if (Ext.getCmp('plan_grid_edit_mnu')) {
Ext.getCmp('plan_grid_edit_mnu').enable();
}
Ext.getCmp('new_run_button').enable();
Ext.getCmp('new_case_button').enable();
Ext.getCmp('edit_plan_list_btn').enable();
if (sm.getCount() > 1) {
if (Ext.getCmp('plan_add_run_mnu')) {
Ext.getCmp('plan_add_run_mnu').disable();
}
Ext.getCmp('new_run_button').disable();
}
},
'rowdeselect': function(sm, i, r){
if (sm.getCount() < 1) {
Ext.getCmp('new_run_button').disable();
Ext.getCmp('new_case_button').disable();
Ext.getCmp('edit_plan_list_btn').disable();
}
}
}
}),
enableColumnHide: true,
tbar: [{
xtype: 'button',
text: 'New Run',
id: 'new_run_button',
disabled: true,
handler: this.newRun.createDelegate(this)
}, {
xtype: 'button',
text: 'New Case',
id: 'new_case_button',
disabled: true,
handler: this.newCase.createDelegate(this)
}, new Ext.Toolbar.Fill(), {
xtype: 'button',
id: 'save_plan_list_btn',
icon: 'extensions/testopia/img/save.png',
iconCls: 'img_button_16x',
tooltip: 'Save this search',
handler: function(b, e){
Testopia.Search.save('plan', Ext.getCmp(cfg.id || 'plan_grid').store.baseParams);
}
}, {
xtype: 'button',
id: 'link_plan_list_btn',
icon: 'extensions/testopia/img/link.png',
iconCls: 'img_button_16x',
tooltip: 'Create a link to this list',
handler: function(b, e){
Testopia.Search.LinkPopup(Ext.getCmp(cfg.id || 'plan_grid').store.baseParams);
}
}, {
xtype: 'button',
id: 'edit_plan_list_btn',
icon: 'extensions/testopia/img/edit.png',
iconCls: 'img_button_16x',
disabled: true,
tooltip: 'Edit Selected Test Plan',
handler: function(){
Testopia.Util.editFirstSelection(Ext.getCmp(cfg.id || 'plan_grid'));
}
}, {
xtype: 'button',
id: 'new_plan_list_btn',
icon: 'extensions/testopia/img/new.png',
iconCls: 'img_button_16x',
tooltip: 'Create a New Test Plan',
handler: function(){
Testopia.TestPlan.NewPlanPopup(params.product_id);
}
}],
viewConfig: {
forceFit: true
}
});
Ext.apply(this, cfg);
this.on('rowcontextmenu', this.onContextClick, this);
this.on('activate', this.onActivate, this);
Ext.getCmp('plan_row_editor').on('afteredit', this.onGridEdit, this);
};
Ext.extend(Testopia.TestPlan.Grid, Ext.grid.GridPanel, {
onContextClick: function(grid, index, e){
grid.selindex = index;
if (!this.menu) { // create context menu on first right click
this.menu = new Ext.menu.Menu({
id: 'plan-ctx-menu',
enableScrolling: false,
items: [{
text: 'Create a New Test Plan',
id: 'plan_menu_new_plan',
icon: 'extensions/testopia/img/new.png',
iconCls: 'img_button_16x',
handler: this.newPlan.createDelegate(this)
}, {
text: 'Add a New Test Run to Selected Plan',
id: 'plan_add_run_mnu',
handler: this.newRun.createDelegate(this)
}, {
text: 'Add a New Test Case to Selected Plans',
id: 'plan_add_case_mnu',
handler: this.newCase.createDelegate(this)
}, {
text: 'Edit',
id: 'plan_grid_edit_mnu',
menu: {
enableScrolling: false,
items: [{
text: 'Type',
handler: function(){
var win = new Ext.Window({
title: 'Change Plan Type',
id: 'plan_type_win',
layout: 'fit',
split: true,
plain: true,
shadow: false,
listeners: {'afterlayout':function(){Ext.getCmp('plan_type_win_types_combo').focus('',10)}},
width: 350,
height: 150,
items: [new Ext.FormPanel({
labelWidth: '40',
bodyStyle: 'padding: 5px',
items: [new Testopia.TestPlan.TypesCombo({
id: 'plan_type_win_types_combo',
fieldLabel: 'Plan Type'
})]
})],
buttons: [{
text: 'Update Type',
handler: function(){
var params = {
plan_type: Ext.getCmp('plan_type_combo').getValue(), 
ids: Testopia.Util.getSelectedObjects(grid, 'plan_id')
};
Testopia.Util.updateFromList('plan', params, grid);
win.close();
}
}, {
text: 'Cancel',
handler: function(){
win.close();
}
}]
});
win.show();
}
}, {
text: 'Tags',
handler: function(){
Testopia.Tags.update('plan', grid);
}    
}]
}
}, {
text: "Reports",
menu: {
enableScrolling: false,
items: [{
text: 'New Status Report',
handler: function(){
Ext.getCmp('object_panel').setActiveTab('dashboardpanel');
var newPortlet = new Ext.ux.Portlet({
title: 'Status Report',
closable: true,
autoScroll: true,
tools: PortalTools
});
newPortlet.url = 'tr_run_reports.cgi?type=status&plan_ids=' + Testopia.Util.getSelectedObjects(grid, 'plan_id');
Testopia.Search.dashboard_urls.push(newPortlet.url);
Ext.getCmp('dashboard_leftcol').add(newPortlet);
Ext.getCmp('dashboard_leftcol').doLayout();
newPortlet.load({
url: newPortlet.url
});
}
}, {
text: 'New Completion Report',
handler: function(){
Ext.getCmp('object_panel').setActiveTab('dashboardpanel');
var newPortlet = new Ext.ux.Portlet({
title: 'Completion Report',
closable: true,
autoScroll: true,
tools: PortalTools
});
newPortlet.url = 'tr_run_reports.cgi?type=completion&plan_ids=' + Testopia.Util.getSelectedObjects(grid, 'plan_id');
Testopia.Search.dashboard_urls.push(newPortlet.url);
Ext.getCmp('dashboard_leftcol').add(newPortlet);
Ext.getCmp('dashboard_leftcol').doLayout();
newPortlet.load({
url: newPortlet.url
});
}
}, {
text: 'New Run Execution Report',
handler: function(){
var win = new Ext.Window({
title: 'Select a date range',
id: 'plan_execution_win',
layout: 'fit',
split: true,
plain: true,
shadow: false,
width: 350,
height: 150,
items: [new Ext.FormPanel({
labelWidth: '40',
bodyStyle: 'padding: 5px',
items: [{
xtype: 'datefield',
id: 'execution_start_date',
fieldLabel: 'Start Date',
name: 'chfieldfrom'
}, {
xtype: 'datefield',
fieldLabel: 'Stop Date',
id: 'execution_stop_date',
emptyText: 'Now',
name: 'chfieldto'
}]
})],
buttons: [{
text: 'Submit',
handler: function(){
Ext.getCmp('object_panel').setActiveTab('dashboardpanel');
var newPortlet = new Ext.ux.Portlet({
title: 'Execution Report',
closable: true,
autoScroll: true,
tools: PortalTools
});
newPortlet.url = 'tr_run_reports.cgi?type=execution&plan_ids=' + Testopia.Util.getSelectedObjects(grid, 'plan_id') + '&chfieldfrom=' + Ext.getCmp('execution_start_date').getValue() + '&chfieldto=' + Ext.getCmp('execution_stop_date').getValue();
Testopia.Search.dashboard_urls.push(newPortlet.url);
Ext.getCmp('dashboard_leftcol').add(newPortlet);
Ext.getCmp('dashboard_leftcol').doLayout();
newPortlet.load({
url: newPortlet.url
});
win.close();
}
}, {
text: 'Cancel',
handler: function(){
win.close();
}
}]
});
win.show();
}
}, {
text: 'New Priority Breakdown Report',
handler: function(){
Ext.getCmp('object_panel').setActiveTab('dashboardpanel');
var newPortlet = new Ext.ux.Portlet({
title: 'Status Report',
closable: true,
autoScroll: true,
tools: PortalTools
});
newPortlet.url = 'tr_run_reports.cgi?type=priority&plan_ids=' + Testopia.Util.getSelectedObjects(grid, 'plan_id');
Testopia.Search.dashboard_urls.push(newPortlet.url);
Ext.getCmp('dashboard_leftcol').add(newPortlet);
Ext.getCmp('dashboard_leftcol').doLayout();
newPortlet.load({
url: newPortlet.url
});
}
}, {
text: 'New Bug Report',
handler: function(){
Ext.getCmp('object_panel').setActiveTab('dashboardpanel');
var newPortlet = new Ext.ux.Portlet({
title: 'Bug Report',
closable: true,
autoScroll: true,
tools: PortalTools
});
newPortlet.url = 'tr_run_reports.cgi?type=bug_grid&plan_ids=' + Testopia.Util.getSelectedObjects(grid, 'plan_id') + '&noheader=1';
Testopia.Search.dashboard_urls.push(newPortlet.url);
Ext.getCmp('dashboard_leftcol').add(newPortlet);
Ext.getCmp('dashboard_leftcol').doLayout();
newPortlet.load({
scripts: true,
url: newPortlet.url
});
}
}, {
text: 'Worst Offender Report',
handler: function(){
Ext.getCmp('object_panel').setActiveTab('dashboardpanel');
var newPortlet = new Ext.ux.Portlet({
title: 'Worst Offender Report',
closable: true,
autoScroll: true,
tools: PortalTools
});
newPortlet.url = 'tr_run_reports.cgi?type=worst&plan_ids=' + Testopia.Util.getSelectedObjects(grid, 'plan_id') + '&noheader=1';
Testopia.Search.dashboard_urls.push(newPortlet.url);
Ext.getCmp('dashboard_leftcol').add(newPortlet);
Ext.getCmp('dashboard_leftcol').doLayout();
newPortlet.load({
scripts: true,
url: newPortlet.url
});
}
}, {
text: 'Missing Cases Report',
handler: function(){
window.open('tr_list_cases.cgi?report_type=missing&plan_ids=' + Testopia.Util.getSelectedObjects(grid, 'plan_id'));
}
}, {
text: 'Case Roll-up Report',
handler: function(){
window.open('tr_list_caseruns.cgi?report_type=rollup&plan_ids=' + Testopia.Util.getSelectedObjects(grid, 'plan_id'));
}
}]
}
}, {
text: 'Refresh List',
icon: 'extensions/testopia/img/refresh.png',
iconCls: 'img_button_16x', 
handler: function(){
grid.store.reload();
} 
}, {
text: 'View Test Plan(s) in a New Tab',
handler: function(){
var plan_ids = Testopia.Util.getSelectedObjects(grid, 'plan_id').split(',');
var i;
for (i = 0; i < plan_ids.length; i += 1) {
window.open('tr_show_plan.cgi?plan_id=' + plan_ids[i]);
}
}
},{
text: 'Export',
menu: [{
text: 'Test Results as CSV',
handler: function(){
window.location = 'tr_list_caseruns.cgi?ctype=csv&viewall=1&plan_id=' + Testopia.Util.getSelectedObjects(grid, 'plan_id');
}
},{
text: 'Cases as CSV',
handler: function(){
window.location='tr_list_cases.cgi?ctype=csv&viewall=1&plan_id=' + Testopia.Util.getSelectedObjects(grid, 'plan_id');
}
},{
text: 'Plans as XML',
handler: function(){
window.location='tr_list_plans.cgi?ctype=xml&viewall=1&plan_id=' + Testopia.Util.getSelectedObjects(grid, 'plan_id');             
}
}]
}]
});
}
e.stopEvent();
if (grid.getSelectionModel().getCount() < 1) {
grid.getSelectionModel().selectRow(index);
}
this.menu.showAt(e.getXY());
},
newPlan: function(){
Testopia.TestPlan.NewPlanPopup(this.params.product_id);
},
newRun: function(){
Testopia.TestRun.NewRunPopup(this.getSelectionModel().getSelected());
},
newCase: function(){
Testopia.TestCase.NewCasePopup(Testopia.Util.getSelectedObjects(this, 'plan_id'), this.getSelectionModel().getSelected().get('product_id'));
},
onGridEdit: function(e){
var ds = this.store;
var myparams = e.record.data;
myparams.action = 'edit';
this.form.submit({
url: "tr_process_plan.cgi",
params: myparams,
success: function(f, a){
ds.commitChanges();
},
failure: function(f, a){
Testopia.Util.error(f, a);
ds.rejectChanges();
}
});
},
onActivate: function(event){
if (!this.store.getCount()) {
this.store.load();
}
}
});
Testopia.TestPlan.NewPlanForm = function(product_id){
var versionsBox = new Testopia.Product.VersionCombo({
id: 'new_plan_form_version_chooser',
hiddenName: 'prod_version',
fieldLabel: "<b>Product Version</b>",
mode: 'local',
params: {
product_id: product_id
}
});
var productsBox = new Testopia.Product.Combo({
id: 'new_plan_form_product_chooser',
hiddenName: 'product_id',
fieldLabel: "<b>Product</b>",
mode: 'local',
value: product_id
});
productsBox.on('select', function(c, r, i){
versionsBox.reset();
versionsBox.store.baseParams.product_id = r.get('id');
versionsBox.store.load();
versionsBox.enable();
});
Testopia.TestPlan.NewPlanForm.superclass.constructor.call(this, {
url: 'tr_new_plan.cgi',
id: 'new_plan_form',
baseParams: {
action: 'add'
},
fileUpload: true,
labelAlign: 'top',
frame: true,
title: 'New Plan',
bodyStyle: 'padding:5px 5px 0',
width: 800,
height: 500,
items: [{
layout: 'column',
items: [{
columnWidth: 0.5,
layout: 'form',
items: [{
xtype: 'textfield',
fieldLabel: '<b>Plan Name</b>',
id: 'new_plan_name',
name: 'plan_name',
anchor: '95%',
allowBlank: false
}, new Testopia.TestPlan.TypesCombo({
id: 'new_plan_form_types_chooser',
mode: 'local',
hiddenName: 'type',
fieldLabel: '<b>Plan Type</b>'
})]
}, {
columnWidth: 0.5,
layout: 'form',
items: [productsBox, versionsBox]
}]
}, {
xtype: 'tabpanel',
height: 280,
activeItem: 0,
items: [{
layout: 'fit',
title: 'Plan Document',
items: [{
id: 'plan_doc',
xtype: 'htmleditor',
name: 'plandoc'
}]
}, new Testopia.Attachment.Form()]
}],
buttons: [{
text: 'Submit',
handler: function(){
if (!Ext.getCmp('new_plan_form').getForm().isValid()) {
return;
}
Ext.getCmp('new_plan_form').getForm().submit({
success: function(form, data){
if (data.result.err) {
alert('One or more attachments were either too large or were empty. These have been ignored.');
}
Ext.Msg.show({
title: 'Plan Created',
msg: 'Plan ' + data.result.plan + ' Created. Would you like to go there now?',
buttons: Ext.Msg.YESNO,
icon: Ext.MessageBox.QUESTION,
fn: function(btn){
if (btn == 'yes') {
window.location = 'tr_show_plan.cgi?plan_id=' + data.result.plan;
}
}
});
try {
Ext.getCmp('newplan-win').close();
}
catch (err) {
}
},
failure: Testopia.Util.error
});
}
}, {
text: 'Cancel',
handler: function(){
if (Ext.getCmp('newplan-win')) {
Ext.getCmp('newplan-win').close();
}
else {
window.location = 'tr_show_product.cgi';
}
}
}]
});
};
Ext.extend(Testopia.TestPlan.NewPlanForm, Ext.form.FormPanel);
Testopia.TestPlan.NewPlanPopup = function(product_id){
var win = new Ext.Window({
id: 'newplan-win',
closable: true,
width: 800,
height: 550,
plain: true,
shadow: false,
layout: 'fit',
items: [new Testopia.TestPlan.NewPlanForm(product_id)]
});
win.show(this);
};
Testopia.TestPlan.ClonePanel = function(plan){
var pbox = new Testopia.Product.Combo({
id: 'plan_clone_product_chooser',
hiddenName: 'product_id',
fieldLabel: 'Copy To Product',
mode: 'local',
width: 550,
value: plan.product_id
});
var vbox = new Testopia.Product.VersionCombo({
id: 'plan_clone_version_chooser',
hiddenName: 'prod_version',
fieldLabel: '<b>Product Version</b>',
params: {
product_id: plan.product_id
},
allowBlank: false
});
var bbox = new Testopia.Build.Combo({
fieldLabel: 'Select a Build',
id: 'plan_clone_build_chooser',
mode: 'local',
hiddenName: 'new_run_build',
params: {
product_id: plan.product_id,
activeonly: 1
}
});
var ebox = new Testopia.Environment.Combo({
fieldLabel: 'Select an Environment',
id: 'plan_clone_environment_chooser',
mode: 'local',
hiddenName: 'new_run_env',
params: {
product_id: plan.product_id,
isactive: 1
}
});
pbox.on('select', function(c, r, i){
vbox.reset();
vbox.store.baseParams.product_id = r.id;
Ext.getCmp('plan_clone_build_chooser').store.baseParams.product_id = r.id;
Ext.getCmp('plan_clone_environment_chooser').store.baseParams.product_id = r.id;
Ext.getCmp('plan_clone_build_chooser').store.load();
Ext.getCmp('plan_clone_environment_chooser').store.load();
if (r.id == plan.product_id) {
Ext.getCmp('copy_categories').disable();
}
else {
Ext.getCmp('copy_categories').enable();
}
vbox.store.load();
vbox.enable();
});
function doSubmit(){
var form = this.getForm();
var p = form.getValues();
if (form.isValid()) {
form.submit({
success: function(f, a){
Ext.Msg.show({
title: 'Plan Copied',
msg: 'Plan ' + a.result.plan_id + ' Created. Would you like to go there now?',
buttons: Ext.Msg.YESNO,
icon: Ext.MessageBox.QUESTION,
fn: function(btn){
if (btn == 'yes') {
window.location = 'tr_show_plan.cgi?plan_id=' + a.result.plan_id;
}
}
});
},
failure: Testopia.Util.error
})
}
}
Testopia.TestPlan.ClonePanel.superclass.constructor.call(this, {
id: 'plan_clone_panel',
url: 'tr_process_plan.cgi',
baseParams: {
action: 'clone'
},
bodyStyle: 'padding: 10px',
border: false,
autoScroll: true,
width: 600,
items: [{
layout: 'table',
border: false,
layoutConfig: {
columns: 2,
width: '100%'
},
items: [{
colspan: 2,
layout: 'form',
border: false,
items: [{
id: 'plan_clone_name',
xtype: 'textfield',
fieldLabel: '<b>New Plan Name</b>',
name: 'plan_name',
allowBlank: false,
width: 550
}, pbox, vbox]
}, {
layout: 'form',
border: false,
items: [{
xtype: 'checkbox',
name: 'copy_attachments',
checked: false,
boxLabel: 'Copy Plan Attachments',
hideLabel: true
}, {
xtype: 'checkbox',
name: 'copy_doc',
checked: true,
boxLabel: 'Copy Plan Document',
hideLabel: true
}, {
xtype: 'hidden',
name: 'plan_id',
value: plan.plan_id
}]
}, {
layout: 'form',
border: false,
items: [{
xtype: 'checkbox',
name: 'copy_tags',
checked: true,
boxLabel: 'Copy Plan Tags',
hideLabel: true
}, {
xtype: 'checkbox',
name: 'copy_perms',
checked: true,
boxLabel: 'Copy Plan Permissions',
hideLabel: true
}]
}, {
layout: 'form',
border: false,
colspan: 2,
items: [{
xtype: 'checkbox',
name: 'keep_plan_author',
checked: false,
boxLabel: 'Maintain original author (unchecking will make me the author of the new plan)',
hideLabel: true
}, {
xtype: 'fieldset',
autoHeight: true,
checkboxToggle: true,
checkboxName: 'copy_cases',
id: 'copy_cases',
title: 'Copy Test Cases',
collapsed: true,
items: [{
xtype: 'checkbox',
id: 'case_copy_plan_ids',
name: 'make_copy',
boxLabel: 'Create a copy (Unchecking will create a link to selected plans)',
hideLabel: true,
listeners: {
'check': function(box, checked){
if (checked === true) {
Ext.getCmp('copy_cases_keep_author').enable();
Ext.getCmp('copy_cases_keep_tester').enable();
}
else {
Ext.getCmp('copy_cases_keep_author').disable();
Ext.getCmp('copy_cases_keep_tester').disable();
}
}
}
}, {
xtype: 'checkbox',
name: 'keep_case_authors',
id: 'copy_cases_keep_author',
checked: false,
disabled: true,
boxLabel: 'Maintain original authors (unchecking will make me the author of the copied cases)',
hideLabel: true
}, {
xtype: 'checkbox',
id: 'copy_cases_keep_tester',
boxLabel: 'Keep Default Tester (unchecking will make you the default tester of copied cases)',
hideLabel: true,
name: 'keep_tester',
checked: true
}, {
xtype: 'checkbox',
name: 'copy_categories',
id: 'copy_categories',
checked: false,
disabled: true,
boxLabel: 'Copy Categories to new product (unchecking will place copied cases in the default category for the selected product)',
hideLabel: true                        
}]
}, {
xtype: 'fieldset',
autoHeight: true,
checkboxToggle: true,
checkboxName: 'copy_runs',
id: 'copy_runs',
title: 'Copy Test Runs',
collapsed: true,
items: [{
xtype: 'checkbox',
name: 'keep_run_managers',
checked: false,
boxLabel: 'Maintain managers (unchecking will make me the manager of the new runs)',
hideLabel: true
}, {
xtype: 'checkbox',
name: 'copy_run_tags',
checked: true,
boxLabel: 'Copy tags from the old run to the new run',
hideLabel: true
}, {
xtype: 'checkbox',
name: 'copy_run_cases',
id: 'copy_run_cases_cbox',
checked: true,
boxLabel: 'Include test cases (unchecking will produce an empty test run)',
hideLabel: true
}, bbox, ebox]
}]
}]
}],
buttons: [{
text: 'Submit',
handler: doSubmit.createDelegate(this)
}, {
text: 'Cancel',
handler: function(){
Ext.getCmp('plan-clone-win').close();
}
}]
});
};
Ext.extend(Testopia.TestPlan.ClonePanel, Ext.form.FormPanel);
Testopia.TestPlan.ClonePopup = function(plan){
var win = new Ext.Window({
id: 'plan-clone-win',
closable: true,
width: 750,
title: 'Create a Copy of Plan ' + plan.plan_id,
height: 500,
plain: true,
shadow: false,
closable: true,
layout: 'fit',
items: [new Testopia.TestPlan.ClonePanel(plan)]
});
win.show();
};
Testopia.Product.Store = function(class_id, auto){
Testopia.Product.Store.superclass.constructor.call(this, {
url: 'tr_quicksearch.cgi',
root: 'products',
listeners: { 'exception': Testopia.Util.loadError },
autoLoad: auto,
id: 'id',
baseParams: {
action: 'getproducts',
class_id: class_id
},
fields: [{
name: 'id',
mapping: 'id'
}, {
name: 'name',
mapping: 'name'
}]
});
};
Ext.extend(Testopia.Product.Store, Ext.data.JsonStore);
Testopia.Product.VersionStore = function(params, auto){
params.action = 'getversions';
Testopia.Product.VersionStore.superclass.constructor.call(this, {
url: 'tr_quicksearch.cgi',
root: 'versions',
listeners: { 'exception': Testopia.Util.loadError },
baseParams: params,
autoLoad: auto,
id: 'id',
fields: [{
name: 'id',
mapping: 'id'
}, {
name: 'name',
mapping: 'name'
}]
});
};
Ext.extend(Testopia.Product.VersionStore, Ext.data.JsonStore);
Testopia.Product.MilestoneStore = function(params, auto){
params.action = 'getmilestones';
Testopia.Product.MilestoneStore.superclass.constructor.call(this, {
url: 'tr_quicksearch.cgi',
root: 'milestones',
listeners: { 'exception': Testopia.Util.loadError },
autoLoad: auto,
baseParams: params,
id: 'id',
fields: [{
name: 'id',
mapping: 'id'
}, {
name: 'name',
mapping: 'name'
}]
});
};
Ext.extend(Testopia.Product.MilestoneStore, Ext.data.JsonStore);
Testopia.Product.Combo = function(cfg){
Testopia.Product.Combo.superclass.constructor.call(this, {
id: cfg.id || 'product_combo',
store: cfg.transform ? false : new Testopia.Product.Store(cfg.params, cfg.mode == 'local' ? true : false),
loadingText: 'Looking up products...',
displayField: 'name',
valueField: 'id',
typeAhead: true,
triggerAction: 'all',
minListWidth: 300,
forceSelection: true,
transform: cfg.transform,
emptyText: 'Please select...'
});
Ext.apply(this, cfg);
this.store.on('load', function(){
if (cfg.value) {
this.setValue(cfg.value);
}
}, this);
};
Ext.extend(Testopia.Product.Combo, Ext.form.ComboBox);
Testopia.Product.VersionCombo = function(cfg){
Testopia.Product.VersionCombo.superclass.constructor.call(this, {
id: cfg.id || 'product_version_combo',
store: cfg.transform ? false : new Testopia.Product.VersionStore(cfg.params, cfg.mode == 'local' ? true : false),
loadingText: 'Looking up versions...',
displayField: 'name',
valueField: 'id',
typeAhead: true,
triggerAction: 'all',
minListWidth: 300,
forceSelection: true,
transform: cfg.transform,
emptyText: 'Please select...'
});
Ext.apply(this, cfg);
this.store.on('load', function(){
if (cfg.value) {
this.setValue(cfg.value);
}
}, this);
};
Ext.extend(Testopia.Product.VersionCombo, Ext.form.ComboBox);
Testopia.Product.MilestoneCombo = function(cfg){
Testopia.Product.MilestoneCombo.superclass.constructor.call(this, {
id: cfg.id || 'milestone_combo',
store: cfg.transform ? false : new Testopia.Product.MilestoneStore(cfg.params, cfg.mode == 'local' ? true : false),
loadingText: 'Looking up milestones...',
displayField: 'name',
valueField: 'id',
typeAhead: true,
triggerAction: 'all',
minListWidth: 300,
forceSelection: true,
transform: cfg.transform,
emptyText: 'Please select...'
});
Ext.apply(this, cfg);
this.store.on('load', function(){
if (cfg.value) {
this.setValue(cfg.value);
}
}, this);
};
Ext.extend(Testopia.Product.MilestoneCombo, Ext.form.ComboBox);
Testopia.TestRun.Grid = function(params, cfg){
params.limit = Ext.state.Manager.get('TESTOPIA_DEFAULT_PAGE_SIZE', 25);
params.current_tab = 'run';
this.params = params;
this.store = new Ext.data.JsonStore({
url: 'tr_list_runs.cgi',
listeners: { 'exception': Testopia.Util.loadError },
baseParams: params,
totalProperty: 'totalResultsAvailable',
root: 'Result',
id: 'run_id',
fields: [{
name: "run_id",
mapping: "run_id"
}, {
name: "plan_id",
mapping: "plan_id"
}, {
name: "summary",
mapping: "summary"
}, {
name: "manager",
mapping: "manager_name"
}, {
name: "start_date",
mapping: "start_date"
}, {
name: "stop_date",
mapping: "stop_date"
}, {
name: "build",
mapping: "build.name"
}, {
name: "environment",
mapping: "environment.name"
}, {
name: "status",
mapping: "status"
}, {
name: "case_count",
mapping: "case_count"
}, {
name: "run_product_version",
mapping: "product_version"
}, {
name: "product_id",
mapping: "product_id"
}, {
name: "passed_pct",
mapping: "passed_pct"
}, {
name: "failed_pct",
mapping: "failed_pct"
}, {
name: "blocked_pct",
mapping: "blocked_pct"
}, {
name: "complete_pct",
mapping: "complete_pct"
}, {
name: "plan_version",
mapping: "plan_version"
}, {
name: "bug_list",
mapping: "bug_list"
}],
remoteSort: true
});
var ds = this.store;
ds.paramNames.sort = "order";
ds.on('beforeload', function(store, o){
store.baseParams.ctype = 'json';
});
var bcombo = new Testopia.Build.Combo({
hiddenName: 'build',
id: 'run_grid_build',
mode: 'remote',
params: {
product_id: params.product_id,
activeonly: 1
},
listeners: {
'startedit': function(){
var pid = Ext.getCmp(cfg.id || 'run_grid').getSelectionModel().getSelected().get('product_id');
if (bcombo.store.baseParams.product_id != pid) {
bcombo.store.baseParams.product_id = pid;
bcombo.store.load();
}
}
}
});
var ecombo = new Testopia.Environment.Combo({
hiddenName: 'environment',
id: 'run_grid_env',
mode: 'remote',
params: {
product_id: params.product_id,
isactive: 1
}, 
listeners: {
'startedit': function(){
var pid = Ext.getCmp(cfg.id || 'run_grid').getSelectionModel().getSelected().get('product_id');
if (ecombo.store.baseParams.product_id != pid) {
ecombo.store.baseParams.product_id = pid;
ecombo.store.load();
}
}
}
});
var vcombo = new Testopia.Product.VersionCombo({
hiddenName: 'run_product_version',
id: 'run_grid_version',
mode: 'remote',
params: {
product_id: params.product_id
}, 
listeners: {
'startedit': function(){
var pid = Ext.getCmp(cfg.id || 'run_grid').getSelectionModel().getSelected().get('product_id');
if (vcombo.store.baseParams.product_id != pid) {
vcombo.store.baseParams.product_id = pid;
vcombo.store.load();
}
}
}
});
this.columns = [{
header: "Run ID",
width: 30,
dataIndex: "run_id",
id: "run_id",
sortable: true,
renderer: Testopia.Util.makeLink.createDelegate(this,['run'],true),
hideable: false
}, {
header: "Summary",
width: 220,
dataIndex: "summary",
id: "run_name",
sortable: true,
editor: {
xtype: 'textfield',
allowBlank: false
}
}, {
header: "Manager Name",
width: 150,
dataIndex: "manager",
id: "manager_name_col",
sortable: true,
hidden: true,
editor: new Testopia.User.Lookup({
hiddenName: 'manager'
}),
renderer: Testopia.Util.ComboRenderer.createDelegate(this)
}, {
header: "Start Date",
width: 110,
dataIndex: "start_date",
sortable: true,
hidden: true
}, {
header: "Stop Date",
width: 110,
dataIndex: "stop_date",
sortable: true,
hidden: true
}, {
header: "Build",
width: 110,
dataIndex: "build",
id: "build_col",
sortable: true,
editor: bcombo,
renderer: Testopia.Util.ComboRenderer.createDelegate(this)
}, {
header: "Enviroment",
width: 110,
dataIndex: "environment",
id: "environment",
sortable: true,
editor: ecombo,
renderer: Testopia.Util.ComboRenderer.createDelegate(this)
}, {
header: "Status",
width: 50,
dataIndex: "status",
id: "status",
sortable: true
}, {
header: "Case Count",
width: 30,
dataIndex: "case_count",
sortable: false,
hidden: true
}, {
header: "Product Version",
width: 150,
dataIndex: "product_version",
id: "product_version",
sortable: true,
hidden: true,
editor: vcombo,
renderer: Testopia.Util.ComboRenderer.createDelegate(this)
}, {
header: "Plan ID",
width: 30,
dataIndex: "plan_id",
sortable: true,
hidden: true,
renderer: Testopia.Util.makeLink.createDelegate(this,['plan'],true)
}, {
header: "Complete",
width: 110,
dataIndex: "complete_pct",
sortable: false,
hideable: true,
renderer: function(v, m, r){
var val = '';
val = val + '<div class="x-progress-wrap" style="width: 98px; height: 15;">';
val = val + '    <div style="position: relative;">';
val = val + '    <div class="x-progress-bar-green" style="width: ' + Math.floor(r.get('passed_pct') * 98) + 'px; height: 14;"></div>';
val = val + '    <div class="x-progress-bar-red" style="width: ' + Math.floor(r.get('failed_pct') * 98) + 'px; height: 14;"></div>';
val = val + '    <div class="x-progress-bar-orange" style="width: ' + Math.floor(r.get('blocked_pct') * 98) + 'px; height: 14;"></div>';
val = val + '    <div class="x-progress-text-main x-hidden" style="font-weight: bold; z-index: 99;">';
val = val + '        <div style="width: 100px; height: 12px;">' + v + '</div>';
val = val + '    </div>';
val = val + '    <div class="x-progress-text-main x-progress-text-back-main" style="font-weight: bold;">';
val = val + '        <div style="width: 100px; height: 12px;">' + v + '</div>';
val = val + '    </div>';
val = val + '    </div>';
val = val + '</div>';
return val;
}
}];
this.form = new Ext.form.BasicForm('testopia_helper_frm', {});
this.bbar = new Testopia.Util.PagingBar('run', this.store);
Testopia.TestRun.Grid.superclass.constructor.call(this, {
title: 'Test Runs',
id: cfg.id || 'run_grid',
loadMask: {
msg: 'Loading Test Runs...'
},
autoExpandColumn: "run_summary",
autoScroll: true,
stripeRows: true,
plugins: [new Ext.ux.grid.RowEditor({
id:'run_row_editor',
saveText: 'Update'
})],
sm: new Ext.grid.RowSelectionModel({
singleSelect: false,
listeners: {
'rowselect': function(sm, i, r){
Ext.getCmp('new_case_to_run_button').enable();
Ext.getCmp('delete_run_list_btn').enable();
Ext.getCmp('edit_run_list_btn').enable();
},
'rowdeselect': function(sm, i, r){
if (sm.getCount() < 1) {
Ext.getCmp('new_case_to_run_button').disable();
Ext.getCmp('delete_run_list_btn').disable();
Ext.getCmp('edit_run_list_btn').disable();
}
}
}
}),
viewConfig: {
forceFit: true
},
tbar: [{
xtype: 'button',
text: 'Add Test Cases to Selected Runs',
id: 'new_case_to_run_button',
disabled: true,
handler: function(){
var run = Ext.getCmp(cfg.id || 'run_grid').getSelectionModel().getSelected();
Testopia.TestRun.AddCasePopup(run);
}
}, new Ext.Toolbar.Fill(), {
xtype: 'button',
id: 'save_run_list_btn',
icon: 'extensions/testopia/img/save.png',
iconCls: 'img_button_16x',
tooltip: 'Save this search',
handler: function(b, e){
Testopia.Search.save('run', Ext.getCmp(cfg.id || 'run_grid').store.baseParams);
}
}, {
xtype: 'button',
id: 'link_run_list_btn',
icon: 'extensions/testopia/img/link.png',
iconCls: 'img_button_16x',
tooltip: 'Create a link to this list',
handler: function(b, e){
Testopia.Search.LinkPopup(Ext.getCmp(cfg.id || 'run_grid').store.baseParams);
}
}, {
xtype: 'button',
id: 'edit_run_list_btn',
icon: 'extensions/testopia/img/edit.png',
iconCls: 'img_button_16x',
disabled: true,
tooltip: 'Edit Selected Test Run',
handler: function(){
Testopia.Util.editFirstSelection(Ext.getCmp(cfg.id || 'run_grid'));
}
}, {
xtype: 'button',
id: 'add_run_list_btn',
icon: 'extensions/testopia/img/new.png',
iconCls: 'img_button_16x',
tooltip: 'Create a New Test Run',
handler: function(){
try {
if (plan) {
Testopia.TestRun.NewRunPopup(plan);
}
}
catch (err) {
window.location = 'tr_new_run.cgi';
}
}
}, {
xtype: 'button',
id: 'delete_run_list_btn',
icon: 'extensions/testopia/img/delete.png',
iconCls: 'img_button_16x',
disabled: true,
tooltip: 'Delete Selected Test Runs',
handler: this.deleteList.createDelegate(this)
}]
});
Ext.apply(this, cfg);
this.on('rowcontextmenu', this.onContextClick, this);
this.on('activate', this.onActivate, this);
Ext.getCmp('run_row_editor').on('afteredit', this.onGridEdit, this);
};
Ext.extend(Testopia.TestRun.Grid, Ext.grid.GridPanel, {
onContextClick: function(grid, index, e){
grid.selindex = index;
if (!this.menu) { // create context menu on first right click
this.menu = new Ext.menu.Menu({
id: 'run-ctx-menu',
enableScrolling: false,
items: [{
text: "Reports",
menu: {
enableScrolling: false,
items: [{
text: 'New Run Status Report',
handler: function(){
Ext.getCmp('object_panel').setActiveTab('dashboardpanel');
var newPortlet = new Ext.ux.Portlet({
title: 'Status Report',
closable: true,
autoScroll: true,
tools: PortalTools
});
newPortlet.url = 'tr_run_reports.cgi?type=status&run_ids=' + Testopia.Util.getSelectedObjects(grid, 'run_id');
Testopia.Search.dashboard_urls.push(newPortlet.url);
Ext.getCmp('dashboard_leftcol').add(newPortlet);
Ext.getCmp('dashboard_leftcol').doLayout();
newPortlet.load({
url: newPortlet.url
});
}
}, {
text: 'New Run Completion Report',
handler: function(){
Ext.getCmp('object_panel').setActiveTab('dashboardpanel');
var newPortlet = new Ext.ux.Portlet({
title: 'Completion Report',
closable: true,
autoScroll: true,
tools: PortalTools
});
newPortlet.url = 'tr_run_reports.cgi?type=completion&run_ids=' + Testopia.Util.getSelectedObjects(grid, 'run_id');
Testopia.Search.dashboard_urls.push(newPortlet.url);
Ext.getCmp('dashboard_leftcol').add(newPortlet);
Ext.getCmp('dashboard_leftcol').doLayout();
newPortlet.load({
url: newPortlet.url
});
}
}, {
text: 'New Run Execution Report',
handler: function(){
var win = new Ext.Window({
title: 'Select a date range',
id: 'run_execution_win',
layout: 'fit',
split: true,
plain: true,
shadow: false,
width: 350,
height: 150,
items: [new Ext.FormPanel({
labelWidth: '40',
bodyStyle: 'padding: 5px',
items: [{
xtype: 'datefield',
id: 'execution_start_date',
fieldLabel: 'Start Date',
name: 'chfieldfrom'
}, {
xtype: 'datefield',
fieldLabel: 'Stop Date',
id: 'execution_stop_date',
emptyText: 'Now',
name: 'chfieldto'
}, new Testopia.User.Lookup({
id: 'exec_tester',
fieldLabel: 'Tester (optional)'
})]
})],
buttons: [{
text: 'Submit',
handler: function(){
Ext.getCmp('object_panel').setActiveTab('dashboardpanel');
var newPortlet = new Ext.ux.Portlet({
title: 'Execution Report',
closable: true,
autoScroll: true,
tools: PortalTools
});
newPortlet.url = 'tr_run_reports.cgi?type=execution&run_ids=' + Testopia.Util.getSelectedObjects(grid, 'run_id') + '&chfieldfrom=' + Ext.getCmp('execution_start_date').getValue() + '&chfieldto=' + Ext.getCmp('execution_stop_date').getValue() + '&tester=' + Ext.getCmp('exec_tester').getValue();
Testopia.Search.dashboard_urls.push(newPortlet.url);
Ext.getCmp('dashboard_leftcol').add(newPortlet);
Ext.getCmp('dashboard_leftcol').doLayout();
newPortlet.load({
url: newPortlet.url
});
win.close();
}
}, {
text: 'Cancel',
handler: function(){
win.close();
}
}]
});
win.show();
}
}, {
text: 'New Priority Breakdown Report',
handler: function(){
Ext.getCmp('object_panel').setActiveTab('dashboardpanel');
var newPortlet = new Ext.ux.Portlet({
title: 'Status Report',
closable: true,
autoScroll: true,
tools: PortalTools
});
newPortlet.url = 'tr_run_reports.cgi?type=priority&run_ids=' + Testopia.Util.getSelectedObjects(grid, 'run_id');
Testopia.Search.dashboard_urls.push(newPortlet.url);
Ext.getCmp('dashboard_leftcol').add(newPortlet);
Ext.getCmp('dashboard_leftcol').doLayout();
newPortlet.load({
url: newPortlet.url
});
}
}, {
text: 'New Run Bug Report',
handler: function(){
Ext.getCmp('object_panel').setActiveTab('dashboardpanel');
var newPortlet = new Ext.ux.Portlet({
title: 'Bug Report',
closable: true,
autoScroll: true,
tools: PortalTools
});
newPortlet.url = 'tr_run_reports.cgi?type=bug_grid&run_ids=' + Testopia.Util.getSelectedObjects(grid, 'run_id') + '&noheader=1';
Testopia.Search.dashboard_urls.push(newPortlet.url);
Ext.getCmp('dashboard_leftcol').add(newPortlet);
Ext.getCmp('dashboard_leftcol').doLayout();
newPortlet.load({
scripts: true,
url: newPortlet.url
});
}
}, {
text: 'Worst Offender Report',
handler: function(){
Ext.getCmp('object_panel').setActiveTab('dashboardpanel');
var newPortlet = new Ext.ux.Portlet({
title: 'Worst Offender Report',
closable: true,
autoScroll: true,
tools: PortalTools
});
newPortlet.url = 'tr_run_reports.cgi?type=worst&run_ids=' + Testopia.Util.getSelectedObjects(grid, 'run_id') + '&noheader=1';
Testopia.Search.dashboard_urls.push(newPortlet.url);
Ext.getCmp('dashboard_leftcol').add(newPortlet);
Ext.getCmp('dashboard_leftcol').doLayout();
newPortlet.load({
scripts: true,
url: newPortlet.url
});
}
}, {
text: 'Case Roll-up Report',
handler: function(){
window.open('tr_list_caseruns.cgi?report_type=rollup&run_ids=' + Testopia.Util.getSelectedObjects(grid, 'run_id'));
}
}]
}
}, {
text: 'Edit',
menu: {
items: [{
text: 'Manager',
handler: function(){
var win = new Ext.Window({
title: 'Change Run Manager',
id: 'run_manager_win',
layout: 'fit',
split: true,
plain: true,
shadow: false,
listeners: {'afterlayout':function(){Ext.getCmp('manager_update').focus('',10)}},
width: 350,
height: 150,
items: [new Ext.FormPanel({
labelWidth: '40',
bodyStyle: 'padding: 5px',
items: [new Testopia.User.Lookup({
id: 'manager_update',
fieldLabel: 'Run Manager'
})]
})],
buttons: [{
text: 'Update Manager',
handler: function(){
Testopia.Util.updateFromList('run', {
manager: Ext.getCmp('manager_update').getValue(),
ids: Testopia.Util.getSelectedObjects(grid, 'run_id')
}, grid);
win.close();
}
}, {
text: 'Cancel',
handler: function(){
win.close();
}
}]
});
win.show();
}
}, {
text: 'Tags',
handler: function(){
Testopia.Tags.update('run', grid);
}
}, {
text: 'Targets',
handler: function(){
var win = new Ext.Window({
title: 'Change Run Targets',
id: 'run_target_win',
layout: 'fit',
split: true,
plain: true,
shadow: false,
listeners: {'afterlayout':function(){Ext.getCmp('target_completion').focus('',10)}},
width: 350,
height: 150,
items: [new Ext.FormPanel({
bodyStyle: 'padding: 5px',
items: [new Ext.form.NumberField({
maxValue: 100,
minValue: 0,
id: 'target_completion',
allowBlank: true,
fieldLabel: 'Target Completion Rate',
hiddenName: 'target_completion',
listeners: {
'valid': function(f){
Ext.getCmp('target_pass').maxValue = f.getValue();
}
}
}), new Ext.form.NumberField({
maxValue: 100,
minValue: 0,
allowBlank: true,
id: 'target_pass',
fieldLabel: 'Target Pass Rate',
hiddenName: 'target_pass'
})]
})],
buttons: [{
text: 'Update Targets',
handler: function(){
Testopia.Util.updateFromList('run', {
target_pass: Ext.getCmp('target_pass').getValue(),
target_completion: Ext.getCmp('target_completion').getValue(),
ids: Testopia.Util.getSelectedObjects(grid, 'run_id')
}, grid);
win.close();
}
}, {
text: 'Cancel',
handler: function(){
win.close();
}
}]
});
win.show();
}
}]
}
}, {
text: 'Clone Selected Test Runs',
icon: 'extensions/testopia/img/copy.png',
iconCls: 'img_button_16x',
handler: function(){
Testopia.TestRun.ClonePopup(grid.getSelectionModel().getSelected().get('product_id'), Testopia.Util.getSelectedObjects(grid, 'run_id'));
}
}, {
text: 'Delete Selected Test Runs',
icon: 'extensions/testopia/img/delete.png',
iconCls: 'img_button_16x',
handler: this.deleteList.createDelegate(this)
}, {
text: 'Refresh List', 
icon: 'extensions/testopia/img/refresh.png',
iconCls: 'img_button_16x',
handler: function(){
grid.store.reload();
} 
}, {
text: 'View Test Run in a New Window',
handler: function(){
window.open('tr_show_run.cgi?run_id=' + grid.store.getAt(grid.selindex).get('run_id'));
}
}, {
text: 'View Run\'s Test Cases in a New Window',
handler: function(){
window.open('tr_list_cases.cgi?run_id=' + grid.store.getAt(grid.selindex).get('run_id'));
}
},{
text: 'Export Results as CSV',
handler: function(){
window.location = 'tr_list_caseruns.cgi?ctype=csv&viewall=1&run_id=' + Testopia.Util.getSelectedObjects(grid, 'run_id');
}
}]
});
}
e.stopEvent();
if (grid.getSelectionModel().getCount() < 1) {
grid.getSelectionModel().selectRow(index);
}
this.menu.showAt(e.getXY());
},
onGridEdit: function(e){
var ds = this.store;
var myparams = e.record.data;
myparams.action = 'edit';
var manager;
if (!myparams.manager.match('@')){
manager = myparams.manager;
delete myparams.manager;
}
this.form.submit({
url: "tr_process_run.cgi",
params: myparams,
success: function(f, a){
myparams.manager = manager;
ds.commitChanges();
},
failure: function(f, a){
Testopia.Util.error(f, a);
myparams.manager = manager;
ds.rejectChanges();
}
});
},
deleteList: function(){
var grid = this;
Ext.Msg.show({
title: 'Confirm Delete?',
msg: RUN_DELETE_WARNING,
buttons: Ext.Msg.YESNO,
animEl: 'run-delete-btn',
icon: Ext.MessageBox.QUESTION,
fn: function(btn){
if (btn == 'yes') {
var testopia_form = new Ext.form.BasicForm('testopia_helper_frm');
testopia_form.submit({
url: 'tr_list_runs.cgi',
params: {
run_ids: Testopia.Util.getSelectedObjects(grid, 'run_id'),
action: 'delete'
},
success: function(data){
Ext.Msg.show({
msg: "Test runs deleted",
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.INFO
});
grid.store.reload();
},
failure: function(f, a){
Testopia.Util.error(f, a);
grid.store.reload();
}
});
}
}
});
},
onActivate: function(event){
if (!this.store.getCount()) {
this.store.load();
}
}
});
Testopia.TestRun.NewRunForm = function(plan){
if (plan.data) {
plan = plan.data;
}
var casegrid = new Testopia.TestCase.Grid({
plan_id: plan.plan_id,
case_status: 'CONFIRMED'
}, {
title: 'Select From Existing Cases',
region: 'center',
id: 'newrun_casegrid',
height: 500
});
this.casegrid = casegrid;
casegrid.on('render', function(g){
for (var i = 0; i < g.getTopToolbar().items.length; i++) {
g.getTopToolbar().items.items[i].destroy();
}
g.getTopToolbar().add({
xtype: 'button',
text: 'Select All',
handler: function(){
casegrid.getSelectionModel().selectAll();
}
}, '->', {
xtype: 'checkbox',
id: 'selectall'
}, ' ', ' Include all CONFIRMED Cases in Plan ' + plan.id);
});
Testopia.TestRun.NewRunForm.superclass.constructor.call(this, {
url: 'tr_new_run.cgi',
id: 'newrunform',
baseParams: {
action: 'add'
},
labelAlign: 'left',
frame: true,
title: 'New Run',
bodyStyle: 'padding:5px 5px 0',
width: 1050,
height: 800,
layout: 'border',
items: [{
region: 'north',
title: 'Filter Cases',
height: 168,
collapsible: true,
listeners: {
'render': function(p){
p.load({
url: 'tr_process_plan.cgi',
params: {
action: 'getfilter',
plan_id: plan.plan_id
},
scripts: true
});
}
},
autoShow: true,
autoScroll: true,
buttons: [{
text: 'Filter',
handler: function(){
var filter = new Ext.form.BasicForm('case_filter');
var params = filter.getValues();
params.plan_id = plan.plan_id;
params.status = 'CONFIRMED';
casegrid.store.baseParams = params;
casegrid.store.load();
}
}]
}, casegrid, {
region: 'south',
xtype: 'form',
url: 'tr_new_run.cgi',
bodyStyle: 'padding: 10px',
id: 'newrunsouth',
height: 200,
items: [{
layout: 'column',
items: [{
columnWidth: 0.5,
layout: 'form',
items: [new Testopia.Product.VersionCombo({
fieldLabel: '<b>Product Version</b>',
hiddenName: 'prod_version',
mode: 'local',
forceSelection: true,
allowBlank: false,
typeAhead: true,
params: {
product_id: plan.product_id
}
}), new Testopia.User.Lookup({
id: 'new_run_manager',
hiddenName: 'manager',
fieldLabel: '<b>Run Manager</b>', 
allowBlank: false
}), new Ext.form.NumberField({
maxValue: 100,
minValue: 0,
allowBlank: true,
id: 'target_completion',
fieldLabel: 'Target Completion Rate',
hiddenName: 'target_completion',
listeners: {
'valid': function(f){
Ext.getCmp('target_pass').maxValue = f.getValue();
}
}
})]
}, {
columnWidth: 0.5,
layout: 'form',
items: [new Testopia.Build.Combo({
fieldLabel: '<b>Build</b>',
hiddenName: 'build',
mode: 'local',
forceSelection: false,
allowBlank: false,
typeAhead: true,
params: {
product_id: plan.product_id,
activeonly: 1
},
emptyText: 'Select or type a new name'
}), new Testopia.Environment.Combo({
fieldLabel: '<b>Environment</b>',
hiddenName: 'environment',
mode: 'local',
forceSelection: false,
allowBlank: false,
typeAhead: true,
params: {
product_id: plan.product_id,
isactive: 1
},
emptyText: 'Select or type a new name'
}), new Ext.form.NumberField({
maxValue: 100,
minValue: 0,
allowBlank: true,
id: 'target_pass',
fieldLabel: 'Target Pass Rate',
hiddenName: 'target_pass'
})]
}]
}, {
xtype: 'textfield',
fieldLabel: '<b>Summary</b>',
layout: 'fit',
id: 'run_summary',
name: 'summary',
anchor: '100%',
width: 600,
allowBlank: false
}, {
xtype: 'hidden',
name: 'plan_id',
value: plan.plan_id
}, {
layout: 'fit',
fieldLabel: 'Notes',
id: 'notes',
xtype: 'textarea',
width: 600,
height: 80
}]
}],
buttons: [{
text: 'Create New Case',
handler: function(){
Testopia.TestCase.NewCasePopup(plan.plan_id, plan.product_id);
}
}, {
text: 'Submit',
handler: function(){
if (!Ext.getCmp('newrunsouth').getForm().isValid()) {
return;
}
var values = {
action: 'add'
};
if (Ext.getCmp('selectall').getValue()) {
values.getall = Ext.getCmp('selectall').getValue() ? 1 : 0;
}
else {
values.case_ids = Testopia.Util.getSelectedObjects(casegrid, 'case_id');
}
if (!Ext.getCmp('build_combo').getValue()) {
values.new_build = Ext.getCmp('build_combo').getRawValue();
}
if (!Ext.getCmp('environment_combo').getValue()) {
values.new_env = Ext.getCmp('environment_combo').getRawValue();
}
Ext.getCmp('newrunsouth').getForm().submit({
params: values,
success: function(form, data){
Ext.Msg.show({
title: 'Test Run Created',
msg: 'Test run ' + data.result.run_id + ' Created. Would you like to go there now?',
buttons: Ext.Msg.YESNO,
icon: Ext.MessageBox.QUESTION,
fn: function(btn){
if (btn == 'yes') {
window.location = 'tr_show_run.cgi?run_id=' + data.result.run_id;
}
}
});
if (Ext.getCmp('plan_run_grid')) {
Ext.getCmp('plan_run_grid').store.reload();
}
},
failure: Testopia.Util.error
});
}
}, {
text: 'Cancel',
type: 'reset',
id: 'nrf_cancel_btn',
handler: function(){
Ext.getCmp('newrunsouth').getForm().reset();
try {
Ext.getCmp('newRun-win').close();
}
catch (err) {
window.location = 'tr_show_product.cgi';
}
}
}]
});
this.on('render', function(){
casegrid.store.load();
Ext.getCmp('new_run_manager').setValue(Testopia_user.login);
});
};
Ext.extend(Testopia.TestRun.NewRunForm, Ext.Panel);
Testopia.TestRun.NewRunPopup = function(plan){
var win = new Ext.Window({
id: 'newRun-win',
closable: true,
width: Ext.getBody().getViewSize().width - 150,
height: Ext.getBody().getViewSize().height - 150,
plain: true,
shadow: false,
layout: 'fit',
items: [new Testopia.TestRun.NewRunForm(plan)]
});
win.show(this);
};
Testopia.TestRun.CloneForm = function(product_id, runs, caselist){
var pgrid = new Testopia.TestPlan.Grid({
product_id: product_id
}, {
id: 'run_clone_plan_grid'
});
var vbox = new Testopia.Product.VersionCombo({
id: 'run_clone_version_chooser',
mode: 'local',
hiddenName: 'new_run_prod_version',
fieldLabel: 'Product Version',
params: {
product_id: product_id
}
});
var bbox = new Testopia.Build.Combo({
fieldLabel: 'Select a Build',
id: 'run_clone_build_chooser',
mode: 'local',
hiddenName: 'new_run_build',
params: {
product_id: product_id,
activeonly: 1
}
});
var ebox = new Testopia.Environment.Combo({
fieldLabel: 'Select an Environment',
id: 'run_clone_environment_chooser',
mode: 'local',
hiddenName: 'new_run_env',
params: {
product_id: product_id,
isactive: 1
}
});
function doSubmit(){
var form = Ext.getCmp('run_clone_frm').getForm();
form.baseParams = {};
if (Ext.getCmp('run_copy_cases').collapsed === false){
switch(Ext.getCmp('copy_cases_radio_group').getGroupValue()){
case 'copy_filtered_cases':
form.baseParams = Ext.getCmp('caserun_search').form.getValues();
break;
case 'copy_selected_cases':
form.baseParams.case_list = Testopia.Util.getSelectedObjects(Ext.getCmp('caserun_grid'), 'caserun_id');
break;
}
}
form.baseParams.action = 'clone';
form.baseParams.ids = runs;
form.baseParams.new_run_build = bbox.getValue();
form.baseParams.new_run_environment = ebox.getValue();
form.baseParams.plan_ids = Testopia.Util.getSelectedObjects(pgrid, 'plan_id');
var p = form.getValues();
if (form.isValid()) {
form.submit({
success: function(f, a){
var msg;
if (a.result.runlist.length == 1) {
msg = a.result.failures.length > 0 ? 'Test cases ' + a.result.failures.join(',') + ' were not included. They are either DISABLED or PROPOSED. <br>' : '';
Ext.Msg.show({
title: 'Run Copied',
msg: msg + 'Run ' + a.result.runlist[0] + ' Created. Would you like to go there now?',
buttons: Ext.Msg.YESNO,
icon: Ext.MessageBox.QUESTION,
fn: function(btn){
if (btn == 'yes') {
window.location = 'tr_show_run.cgi?run_id=' + a.result.runlist[0];
}
}
});
}
else {
msg = a.result.failures.length > 0 ? a.result.failures.join.length + ' Test cases were not included. They are either DISABLED or PROPOSED. <a href="tr_list_cases.cgi?case_id=' + a.result.failures.join(',') + '">View List</a> <br>' : '';
Ext.Msg.show({
title: 'Test Run Copied',
msg: msg + a.result.runlist.length + ' Test runs Copied successfully. <a href="tr_list_runs.cgi?run_id=' + a.result.runlist.join(',') + '">View List</a>',
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.INFO
});
}
},
failure: Testopia.Util.error
})
}
}
Testopia.TestRun.CloneForm.superclass.constructor.call(this, {
id: 'run_clone_form',
border: false,
width: 600,
layout: 'border',
items: [{
region: 'north',
layout: 'fit',
border: false,
height: 300,
items: [pgrid]
}, {
region: 'center',
xtype: 'form',
url: 'tr_list_runs.cgi',
title: 'Clone Options',
autoScroll: true,
id: 'run_clone_frm',
border: false,
frame: true,
bodyStyle: 'padding: 10px',
labelWidth: 160,
height: 350,
items: [{
layout: 'table',
border: false,
autoScroll: true,
layoutConfig: {
columns: 2,
width: '100%'
},
items: [{
colspan: 2,
layout: 'form',
border: false,
items: [{
id: 'run_clone_name',
xtype: 'textfield',
fieldLabel: 'New Run Summary',
name: 'new_run_summary',
width: 500
}]
}, {
layout: 'form',
border: false,
items: [vbox, bbox, ebox]
}, {
layout: 'form',
border: false,
items: [{
xtype: 'checkbox',
name: 'copy_tags',
checked: true,
boxLabel: 'Copy Run Tags',
hideLabel: true
}, {
xtype: 'checkbox',
name: 'copy_filters',
checked: true,
boxLabel: 'Copy Run Filters',
hideLabel: true
}, {
xtype: 'hidden',
id: 'run_clone_product_id',
name: 'product_id',
value: product_id
}]
}, {
colspan: 2,
layout: 'form',
border: false,
items: [{
xtype: 'checkbox',
name: 'keep_run_manager',
checked: false,
boxLabel: 'Maintain original manager (unchecking will make me the manager of the new run)',
hideLabel: true
}, {
xtype: 'fieldset',
autoHeight: true,
checkboxToggle: true,
checkboxName: 'copy_cases',
id: 'run_copy_cases',
title: 'Copy Test Cases',
collapsed: caselist ? false : true,
items: [{
xtype: 'radio',
name: 'copy_cases_options',
id: 'copy_cases_radio_group',
inputValue: 'copy_all_cases',
checked: true,
boxLabel: 'Include all CONFIRMED cases in selected run(s)',
hideLabel: true
}, {
xtype: 'radio',
name: 'copy_cases_options',
inputValue: 'copy_filtered_cases',
boxLabel: 'Only include cases that match the selected filter',
hideLabel: true
}, {
xtype: 'radio',
name: 'copy_cases_options',
inputValue: 'copy_selected_cases',
boxLabel: 'Only include cases that are currently selected',
checked: caselist ? true : false,
hideLabel: true                            
}, {
xtype: 'checkbox',
name: 'keep_indexes',
checked: true,
boxLabel: 'Copy Case Indexes',
hideLabel: true
}, {
xtype: 'checkbox',
name: 'keep_statuses',
boxLabel: 'Maintain status of copied cases (unchecking will set case copies to IDLE (Not Run))',
hideLabel: true
}]
}]
}]
}]
}],
buttons: [{
text: 'Submit',
handler: doSubmit.createDelegate(this)
}, {
text: 'Cancel',
handler: function(){
Ext.getCmp('run-clone-win').close();
}
}]
});
};
Ext.extend(Testopia.TestRun.CloneForm, Ext.Panel);
Testopia.TestRun.ClonePopup = function(product_id, runs, caselist){
var win = new Ext.Window({
id: 'run-clone-win',
closable: true,
width: 800,
height: 600,
plain: true,
shadow: false,
layout: 'fit',
items: [new Testopia.TestRun.CloneForm(product_id, runs, caselist)]
});
var pg = Ext.getCmp('run_clone_plan_grid');
Ext.apply(pg, {
title: 'Select plans to clone runs to'
});
win.show(this);
var pchooser = new Testopia.Product.Combo({
id: 'run_clone_win_product_chooser',
mode: 'local',
value: product_id
});
pchooser.on('select', function(c, r, i){
pg.store.baseParams = {
ctype: 'json',
product_id: r.get('id')
};
Ext.getCmp('run_clone_version_chooser').reset();
Ext.getCmp('run_clone_build_chooser').reset();
Ext.getCmp('run_clone_environment_chooser').reset();
Ext.getCmp('run_clone_version_chooser').store.baseParams.product_id = r.id;
Ext.getCmp('run_clone_build_chooser').store.baseParams.product_id = r.id;
Ext.getCmp('run_clone_environment_chooser').store.baseParams.product_id = r.id;
Ext.getCmp('run_clone_version_chooser').store.load();
Ext.getCmp('run_clone_build_chooser').store.load();
Ext.getCmp('run_clone_environment_chooser').store.load();
if (r.get('id') != product_id) {
Ext.getCmp('run_clone_build_chooser').allowBlank = false;
Ext.getCmp('run_clone_environment_chooser').allowBlank = false;
Ext.getCmp('run_clone_version_chooser').allowBlank = false;
}
else {
Ext.getCmp('run_clone_build_chooser').allowBlank = true;
Ext.getCmp('run_clone_environment_chooser').allowBlank = true;
Ext.getCmp('run_clone_version_chooser').allowBlank = true;            
}
Ext.getCmp('run_clone_product_id').setValue(r.get('id'));
pg.store.load();
});
pg.getTopToolbar().removeAll();
pg.getTopToolbar().add('Product: ', pchooser);
pg.getSelectionModel().un('rowselect', pg.getSelectionModel().events['rowselect'].listeners[0].fn);
pg.getSelectionModel().un('rowdeselect', pg.getSelectionModel().events['rowdeselect'].listeners[0].fn);
pg.store.load();
};
Testopia.TestRun.AddCaseForm = function(run){
if (run.data) {
run = run.data;
}
var casegrid = new Testopia.TestCase.Grid({
plan_id: run.plan_id,
case_status: 'CONFIRMED',
exclude: run.run_id
}, {
title: 'Select From Existing Cases',
region: 'center',
id: 'newrun_casegrid',
height: 500
});
casegrid.on('render', function(g){
for (var i = 0; i < g.getTopToolbar().items.length; i++) {
g.getTopToolbar().items.items[i].destroy();
}
g.getTopToolbar().add({
xtype: 'button',
text: 'Select All',
handler: function(){
casegrid.getSelectionModel().selectAll();
}
});
casegrid.store.load();
});
Testopia.TestRun.AddCaseForm.superclass.constructor.call(this, {
url: 'tr_new_run.cgi',
id: 'add_cases_form',
title: 'Add Cases to Run',
bodyStyle: 'padding:5px 5px 0',
width: 1050,
height: 800,
layout: 'border',
items: [{
region: 'north',
title: 'Filter Cases',
height: 172,
collapsible: true,
listeners: {
'render': function(p){
p.load({
url: 'tr_process_plan.cgi',
params: {
action: 'getfilter',
plan_id: run.plan_id
},
scripts: true
});
}
},
autoShow: true,
autoScroll: true,
buttons: [{
text: 'Filter',
handler: function(){
var filter = new Ext.form.BasicForm('case_filter');
var params = filter.getValues();
params.plan_id = run.plan_id;
params.exclude  = run.run_id;
params.status = 'CONFIRMED';
params.limit = Ext.getCmp('case_pager').pageSize;
casegrid.store.baseParams = params;
casegrid.store.load();
}
}]
}, casegrid],
buttons: [{
text: 'Add Selected Cases to Run',
handler: function(){
var form = new Ext.form.BasicForm('testopia_helper_frm');
form.submit({
url: 'tr_list_cases.cgi',
params: {
action: 'update',
addruns: run.run_id,
ids: Testopia.Util.getSelectedObjects(casegrid, 'case_id')
},
success: function(){
if (Ext.getCmp('add_case_to_run_win')) {
Ext.getCmp('add_case_to_run_win').close();
}
if (Ext.getCmp('caserun_grid')) {
Ext.getCmp('caserun_grid').store.reload();
}
},
failure: Testopia.Util.error
});
}
}]
});
};
Ext.extend(Testopia.TestRun.AddCaseForm, Ext.Panel);
Testopia.TestRun.AddCasePopup = function(run){
var win = new Ext.Window({
id: 'add_case_to_run_win',
closable: true,
width: Ext.getBody().getViewSize().width - 150,
height: Ext.getBody().getViewSize().height - 150,
plain: true,
shadow: false,
layout: 'fit',
items: [new Testopia.TestRun.AddCaseForm(run)]
});
win.show(this);
};
Testopia.TestRun.FiltersList = function(run){
this.store = new Ext.data.JsonStore({
url: 'tr_process_run.cgi',
listeners: { 'exception': Testopia.Util.loadError },
baseParams: {
action: 'getfilters',
run_id: run.run_id
},
root: 'filters',
fields: ["name", "query"]
});
var ds = this.store;
this.columns = [{
header: "Name",
width: 30,
dataIndex: "name",
sortable: true
}];
Testopia.TestRun.FiltersList.superclass.constructor.call(this, {
title: "Filters",
id: "run_filter_grid",
loadMask: {
msg: "Loading Filters ..."
},
autoScroll: true,
sm: new Ext.grid.RowSelectionModel({
singleSelect: true,
listeners: {
'rowselect': function(sm, index, r){
var name = r.get('name');
Ext.getCmp('object_panel').setActiveTab('caserun-panel');
var params = Testopia.Util.urlQueryToJSON(r.get('query'));
var f = document.getElementById('caserun_filter_form');
for (var i = 0; i < f.length; i++) {
if (f[i].type == 'select-multiple') {
for (var k = 0; k < f[i].options.length; k++) {
f[i].options[k].selected = false;
}
var list = params[f[i].name];
if (!list) {
continue;
}
if (typeof list != 'object') {
list = new Array(list);
}
for (j = 0; j < list.length; j++) {
for (k = 0; k < f[i].options.length; k++) {
if (f[i].options[k].value == list[j]) {
f[i].options[k].selected = true;
break;
}
}
}
}
else {
f[i].value = params[f[i].name];
}
}
Ext.getCmp('caserun_grid').store.baseParams = params;
Ext.getCmp('caserun_grid').store.load();
}
}
}),
viewConfig: {
forceFit: true
}
});
this.on('rowcontextmenu', this.onContextClick, this);
this.on('activate', this.onActivate, this);
};
Ext.extend(Testopia.TestRun.FiltersList, Ext.grid.GridPanel, {
onContextClick: function(grid, index, e){
if (!this.menu) { // create context menu on first right click
this.menu = new Ext.menu.Menu({
id: 'run_filter_ctx',
items: [{
text: 'Delete Saved Filter', 
handler: function(){
var form = new Ext.form.BasicForm('testopia_helper_frm', {});
form.submit({
url: 'tr_process_run.cgi',
params: {
action: 'delete_filter',
query_name: grid.store.getAt(index).get('name'),
run_id: grid.store.baseParams.run_id
},
success: function(){
Testopia.Util.notify.msg('Filter removed', 'filter removed successfully');
grid.store.reload();
},
failure: Testopia.Util.error
});
}
}]
});
}
e.stopEvent();
this.menu.showAt(e.getXY());
},
onActivate: function(event){
if (!this.store.getCount()) {
this.store.load();
}
}
});
Testopia.BugReport = function(params){
params.type = 'bug';
this.store = new Ext.data.GroupingStore({
url: 'tr_run_reports.cgi',
baseParams: params,
reader: new Ext.data.JsonReader({
root: 'Result',
fields: [{
name: "case_id",
mapping: "case_id"
}, {
name: "run_id",
mapping: "run_id"
}, {
name: "bug_id",
mapping: "bug_id"
}, {
name: "case_status",
mapping: "case_status"
}, {
name: "bug_status",
mapping: "bug_status"
}, {
name: "severity",
mapping: "bug_severity"
}]
}),
remoteSort: false,
sortInfo: {
field: 'run_id',
direction: "ASC"
},
groupField: 'bug_id'
});
this.store.isTreport = true;
this.view = new Ext.grid.GroupingView({
forceFit: true,
groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Items" : "Item"]})'
});
this.columns = [{
header: 'Run',
dataIndex: 'run_id',
sortable: true,
hideable: true,
groupRenderer: function(v){
return v;
},
renderer: Testopia.Util.makeLink.createDelegate(this,['run'],true)
}, {
header: 'Case',
dataIndex: 'case_id',
sortable: true,
hideable: true,
groupRenderer: function(v){
return v;
},
renderer: Testopia.Util.makeLink.createDelegate(this,['case'],true)
}, {
header: 'Bug',
dataIndex: 'bug_id',
sortable: true,
hideable: true,
groupRenderer: function(v){
return v;
},
renderer: Testopia.Util.makeLink.createDelegate(this,['bug'],true)
}, {
header: 'Bug Status',
dataIndex: 'bug_status',
sortable: true,
hideable: true
}, {
header: 'Case Status',
dataIndex: 'case_status',
sortable: true,
hideable: true
}, {
header: 'Severity',
dataIndex: 'severity',
sortable: true,
hideable: true
}];
Testopia.BugReport.superclass.constructor.call(this, {
sm: new Ext.grid.RowSelectionModel(),
layout: 'fit',
height: 250,
autoScroll: true
});
};
Ext.extend(Testopia.BugReport, Ext.grid.GridPanel);
Testopia.TestRun.ProgressBar = function(cfg){
Testopia.TestRun.ProgressBar.superclass.constructor.call(this, cfg);
};
Ext.extend(Testopia.TestRun.ProgressBar, Ext.ProgressBar, {
onRender: function(ct, position){
Ext.ProgressBar.superclass.onRender.call(this, ct, position);
var tpl = new Ext.Template('<div class="{cls}-wrap">', '<div style="position:relative">', '<div class="{cls}-bar-green"></div>', '<div class="{cls}-bar-red"></div>', '<div class="{cls}-bar-orange"></div>', '<div class="{cls}-text-main" style="font-weight: bold">', '<div>&#160;</div>', '</div>', '<div class="{cls}-text-main {cls}-text-back-main" style="font-weight: bold">', '<div>&#160;</div>', '</div>', '</div>', '</div>');
if (position) {
this.el = tpl.insertBefore(position, {
cls: this.baseCls
}, true);
}
else {
this.el = tpl.append(ct, {
cls: this.baseCls
}, true);
}
if (this.id) {
this.el.dom.id = this.id;
}
this.progressBar = Ext.get(this.el.dom.firstChild);
this.gbar = Ext.get(this.progressBar.dom.firstChild);
this.rbar = Ext.get(this.gbar.dom.nextSibling);
this.obar = Ext.get(this.rbar.dom.nextSibling);
if (this.textEl) {
this.textEl = Ext.get(this.textEl);
delete this.textTopEl;
}
else {
this.textTopEl = Ext.get(this.progressBar.dom.childNodes[3]);
var textBackEl = Ext.get(this.progressBar.dom.childNodes[4]);
this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');
this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);
this.textEl.setWidth(this.progressBar.offsetWidth);
}
if (this.gvalue || this.rvalue || this.ovalue) {
this.updateProgress(this.gvalue, this.rvalue, this.ovalue, this.text);
}
else {
this.updateText(this.text);
}
this.setSize(this.width || 'auto', 'auto');
this.progressBar.setHeight(this.progressBar.offsetHeight);
},
updateProgress: function(gvalue, rvalue, ovalue, text){
this.gvalue = gvalue || 0;
this.rvalue = rvalue || 0;
this.ovalue = ovalue || 0;
if (text) {
this.updateText(text);
}
var gw = Math.floor(gvalue * this.el.dom.firstChild.offsetWidth);
var rw = Math.floor(rvalue * this.el.dom.firstChild.offsetWidth);
var ow = Math.floor(ovalue * this.el.dom.firstChild.offsetWidth);
this.gbar.setWidth(gw);
this.rbar.setWidth(rw);
this.obar.setWidth(ow);
return this;
},
setSize: function(w, h){
Ext.ProgressBar.superclass.setSize.call(this, w, h);
if (this.textTopEl) {
this.textEl.setSize(this.el.dom.offsetWidth, this.el.dom.offsetHeight);
}
return this;
}
});
Testopia.Search.save = function(type, params){
var loc;
var ntype;
if (type == 'dashboard') {
ntype = 3;
loc = Testopia.Search.dashboard_urls.join('::>');
}
else 
if (type == 'custom') {
loc = params;
params = {
report: true
};
ntype = 1;
}
else {
if (type == 'caserun') {
params.current_tab = 'case_run';
}
else {
params.current_tab = type;
}
if (params.report) {
loc = 'tr_' + type + '_reports.cgi?';
ntype = 1;
}
else {
loc = 'tr_list_' + type + 's.cgi?';
ntype = 0;
}
loc = loc + Testopia.Util.JSONToURLQuery(params, '', ['ctype']);
}
var form = new Ext.form.BasicForm('testopia_helper_frm', {});
Ext.Msg.prompt('Save As', '', function(btn, text){
if (btn == 'ok') {
form.submit({
url: 'tr_query.cgi',
params: {
action: 'save_query',
query_name: text,
query_part: loc,
type: ntype
},
success: function(){
if (Ext.getCmp('searches_grid')) {
Ext.getCmp('searches_grid').store.load();
}
if (Ext.getCmp('reports_grid')) {
Ext.getCmp('reports_grid').store.load();
}
if (Ext.getCmp('dashboard_grid')) {
Ext.getCmp('dashboard_grid').store.load();
}
Testopia.Util.notify.msg('Saved', 'Your search or report was saved.');
},
failure: Testopia.Util.error
});
}
});
};
Testopia.Search.fillInForm = function(type, params, name){
var f = document.getElementById(type + '_search_form');
for (var i=0; i < f.length; i++){
if (f[i].type == 'select-multiple'){
for (k=0; k < f[i].options.length; k++){
f[i].options[k].selected = false;
}
var list = params[f[i].name];
if(!list){
continue;
}
if (typeof list != 'object'){
list = new Array(list);
}
for (j=0; j < list.length; j++){
for (k=0; k < f[i].options.length; k++){
if(f[i].options[k].value == list[j]){
f[i].options[k].selected = true;
break;
}
}
}
}
else{
if (params[f[i].name]){
f[i].value = params[f[i].name] || '';
}
}
}
};
Testopia.Search.DashboardPanel = function(cfg){
Testopia.Search.DashboardPanel.superclass.constructor.call(this, {
title: cfg.title || 'Dashboard',
layout: 'fit',
closable: cfg.closable || false,
id: cfg.id || 'dashboardpanel',
tbar: [{
xtype: 'button',
text: 'Add Custom Panel',
handler: function(b, e){
Ext.Msg.prompt('Enter URL', '', function(btn, text){
if (btn == 'ok') {
var url = text + '&noheader=1';
Testopia.Search.dashboard_urls.push(url);
var newPortlet = new Ext.ux.Portlet({
title: 'Custom',
closable: true,
autoScroll: true,
tools: PortalTools,
url: url
});
Ext.getCmp('dashboard_leftcol').add(newPortlet);
Ext.getCmp('dashboard_leftcol').doLayout();
newPortlet.load({
url: url,
scripts: false
});
}
});
}
}, new Ext.Toolbar.Fill()],
items: [{
xtype: 'portal',
margins: '35 5 5 0',
items: [{
columnWidth: 0.5,
baseCls: 'x-plain',
bodyStyle: 'padding:10px 10px 10px 10px',
id: cfg.lc || 'dashboard_leftcol',
items: [{
title: ' ',
hidden: true
}]
}, {
columnWidth: 0.5,
baseCls: 'x-plain',
bodyStyle: 'padding:10px 10px 10px 10px',
id: cfg.rc || 'dashboard_rightcol',
items: [{
title: ' ',
hidden: true
}]
}]
}]
});
this.on('activate', this.onActivate, this);
};
Ext.extend(Testopia.Search.DashboardPanel, Ext.Panel, {
onActivate: function(p){
p.doLayout();
}
});
Testopia.Search.Popup = function(tab, params){
var win = new Ext.Window({
id: 'search_win',
closable: true,
width: Ext.getBody().getViewSize().width - 150,
height: Ext.getBody().getViewSize().height - 150,
plain: true,
shadow: false,
layout: 'fit',
items: [new Testopia.Search.Panel(tab, params)]
});
win.show();
};
Testopia.Search.Panel = function(tab, params){
params = params || {};
Testopia.Search.Panel.superclass.constructor.call(this,{
title: 'Create a Search',
id: 'search_panel',
autoScroll: true,
activeTab: tab + '_search_panel',
defaults: {
bodyStyle:'padding:10px',
autoScroll: true
},
items:[
new Testopia.Search.PlansForm(params),
new Testopia.Search.CasesForm(params),
new Testopia.Search.RunsForm(params),
new Testopia.Search.CaseRunsForm(params)
]
});
};
Ext.extend(Testopia.Search.Panel, Ext.TabPanel);
Testopia.Search.PlansForm = function(params){
this.params = params;
Testopia.Search.PlansForm.superclass.constructor.call(this,{
title: 'Plan Search',
id: 'plan_search_panel',
layout:'fit',
autoLoad: {
url: 'tr_query.cgi?current_tab=plan',
params: params,
scripts: true,
text: 'Loading search form...',
callback: Testopia.Search.fillInForm.createDelegate(this,['plan',this.params])
},
buttons:[{
text: 'Submit',
handler: function(){
var form = new Ext.form.BasicForm('plan_search_form');
var values = form.getValues();
var searchnum = Math.round(Math.random()*100);
try {
Ext.getCmp('search_win').close();
}
catch(err){}
if (params.report){
Ext.getCmp('object_panel').add(new Ext.Panel({
id: 'plan_search' + searchnum, 
closable: true,
title: 'Plan Report',
autoScroll: true,
listeners: { 'render': function(){
this.load({
url: 'tr_plan_reports.cgi',
params: values
});
}},
tbar:[new Ext.Toolbar.Fill(),
{
xtype: 'button',
id: 'save_plan_report_btn',
icon: 'extensions/testopia/img/save.png',
iconCls: 'img_button_16x',
tooltip: 'Save this report',
handler: function(b,e){
Testopia.Search.save('plan', values);
}
},{
xtype: 'button',
id: 'link_plan_report_btn',
icon: 'extensions/testopia/img/link.png',
iconCls: 'img_button_16x',
tooltip: 'Create a link to this report',
handler: function(b,e){
Testopia.Search.LinkPopup(values);
}
}]
}));
Ext.getCmp('object_panel').activate('plan_search' + searchnum);
}
else{
Ext.getCmp('object_panel').add(new Testopia.TestPlan.Grid(values,{
id: 'plan_search' + searchnum, 
closable: true,
title: 'Plan Search'
}));
Ext.getCmp('object_panel').activate('plan_search' + searchnum);
}
}
}]
});
this.on('activate', this.onActivate, this);
};
Ext.extend(Testopia.Search.PlansForm, Ext.Panel,{
onActivate: function(event){
if (!this.rendered){
return;
}
if (Ext.get('case_search_form')){
Ext.get('case_search_form').remove();
}
if (Ext.get('run_search_form')){
Ext.get('run_search_form').remove();
}
if (Ext.get('caserun_search_form')){
Ext.get('caserun_search_form').remove();
}
this.params.current_tab = 'plan';
this.load({
url: 'tr_query.cgi',
params: this.params,
scripts: true,
text: 'Loading search form...',
callback: Testopia.Search.fillInForm.createDelegate(this,['plan',this.params])
});
}
});
Testopia.Search.CasesForm = function(params){
this.params = params;
Testopia.Search.CasesForm.superclass.constructor.call(this,{
title: 'Case Search',
id: 'case_search_panel',
layout:'fit',
autoLoad: {
url: 'tr_query.cgi?current_tab=case',
params: params,
scripts: true,
text: 'Loading search form...',
callback: Testopia.Search.fillInForm.createDelegate(this,['case',this.params])
},
buttons:[{
text: 'Submit',
handler: function(){
var form = new Ext.form.BasicForm('case_search_form');
var values = form.getValues();
var searchnum = Math.round(Math.random()*100);
try {
Ext.getCmp('search_win').close();
}
catch(err){}
if (params.report){
Ext.getCmp('object_panel').add(new Ext.Panel({
id: 'case_search' + searchnum, 
closable: true,
title: 'Case Report',
autoScroll: true,
listeners: { 'render': function(){
this.load({
url: 'tr_case_reports.cgi',
params: values
});
}},
tbar:[new Ext.Toolbar.Fill(),
{
xtype: 'button',
id: 'save_case_report_btn',
icon: 'extensions/testopia/img/save.png',
iconCls: 'img_button_16x',
tooltip: 'Save this report',
handler: function(b,e){
Testopia.Search.save('case', values);
}
},{
xtype: 'button',
id: 'link_case_report_btn',
icon: 'extensions/testopia/img/link.png',
iconCls: 'img_button_16x',
tooltip: 'Create a link to this report',
handler: function(b,e){
Testopia.Search.LinkPopup(values);
}
}]
}));
Ext.getCmp('object_panel').activate('case_search' + searchnum);
}
else{
Ext.getCmp('object_panel').add(new Testopia.TestCase.Grid(values,{
id: 'case_search' + searchnum, 
closable: true,
title: 'Case Search'
}));
}
Ext.getCmp('object_panel').activate('case_search' + searchnum);
}
}]
});
this.on('activate', this.onActivate, this);
};
Ext.extend(Testopia.Search.CasesForm, Ext.Panel,{
onActivate: function(event){
if (!this.rendered){
return;
}
if (Ext.get('run_search_form')){
Ext.get('run_search_form').remove();
}
if (Ext.get('plan_search_form')){
Ext.get('plan_search_form').remove();
}
if (Ext.get('caserun_search_form')){
Ext.get('caserun_search_form').remove();
}
this.params.current_tab = 'case';
this.load({
url: 'tr_query.cgi',
params: this.params,
scripts: true,
text: 'Loading search form...',
callback: Testopia.Search.fillInForm.createDelegate(this,['case',this.params])
});
}
});
Testopia.Search.RunsForm = function(params){
this.params = params;
Testopia.Search.RunsForm.superclass.constructor.call(this,{
title: 'Run Search',
id: 'run_search_panel',
layout:'fit',
autoLoad: {
url: 'tr_query.cgi?current_tab=run',
params: params,
scripts: true,
text: 'Loading search form...',
callback: Testopia.Search.fillInForm.createDelegate(this,['run',this.params])
},
buttons:[{
text: 'Submit',
handler: function(){
var form = new Ext.form.BasicForm('run_search_form');
var values = form.getValues();
if (params.qname)
values.qname = params.qname;
var searchnum = Math.round(Math.random()*100);
try {
Ext.getCmp('search_win').close();
}
catch(err){}
if (params.report){
Ext.getCmp('object_panel').add(new Ext.Panel({
id: 'run_search' + searchnum, 
closable: true,
title: 'Run Report',
autoScroll: true,
listeners: { 'render': function(){
this.load({
url: 'tr_run_reports.cgi',
params: values
});
}},
tbar:[new Ext.Toolbar.Fill(),
{
xtype: 'button',
id: 'save_run_report_btn',
icon: 'extensions/testopia/img/save.png',
iconCls: 'img_button_16x',
tooltip: 'Save this report',
handler: function(b,e){
Testopia.Search.save('run', values);
}
},{
xtype: 'button',
id: 'link_run_report_btn',
icon: 'extensions/testopia/img/link.png',
iconCls: 'img_button_16x',
tooltip: 'Create a link to this report',
handler: function(b,e){
Testopia.Search.LinkPopup(values);
}
}]
}));
Ext.getCmp('object_panel').activate('run_search' + searchnum);
}
else{
Ext.getCmp('object_panel').add(new Testopia.TestRun.Grid(values,{
id: 'run_search' + searchnum, 
closable: true,
title: 'Run Search'
}));
}
Ext.getCmp('object_panel').activate('run_search' + searchnum);
}
}]
});
this.on('activate', this.onActivate, this);
};
Ext.extend(Testopia.Search.RunsForm, Ext.Panel,{
onActivate: function(event){
if (!this.rendered){
return;
}
if (Ext.get('case_search_form')){
Ext.get('case_search_form').remove();
}
if (Ext.get('plan_search_form')){
Ext.get('plan_search_form').remove();
}
if (Ext.get('caserun_search_form')){
Ext.get('caserun_search_form').remove();
}
this.params.current_tab = 'run';
this.load({
url: 'tr_query.cgi',
params: this.params,
scripts: true,
text: 'Loading search form...',
callback: Testopia.Search.fillInForm.createDelegate(this,['run',this.params])
});
}
});
Testopia.Search.CaseRunsForm = function(params){
this.params = params;
Testopia.Search.CaseRunsForm.superclass.constructor.call(this,{
title: 'Case-Run Search',
id: 'caserun_search_panel',
layout:'fit',
autoLoad:{
url: 'tr_query.cgi?current_tab=case_run',
params: params,
scripts: true,
text: 'Loading search form...',
callback: Testopia.Search.fillInForm.createDelegate(this,['caserun',this.params])
},
buttons:[{
text: 'Submit',
handler: function(){
var form = new Ext.form.BasicForm('caserun_search_form');
var values = form.getValues();
var searchnum = Math.round(Math.random()*100);
try {
Ext.getCmp('search_win').close();
}
catch(err){}
if (params.report){
Ext.getCmp('object_panel').add(new Ext.Panel({
id: 'case_run_search' + searchnum, 
closable: true,
title: 'Case-Run Report',
autoScroll: true,
listeners: { 'render': function(){
this.load({
url: 'tr_caserun_reports.cgi',
params: values
});
}},
tbar:[new Ext.Toolbar.Fill(),
{
xtype: 'button',
id: 'save_caserun_report_btn',
icon: 'extensions/testopia/img/save.png',
iconCls: 'img_button_16x',
tooltip: 'Save this report',
handler: function(b,e){
Testopia.Search.save('caserun', values);
}
},{
xtype: 'button',
id: 'link_plan_list_btn',
icon: 'extensions/testopia/img/link.png',
iconCls: 'img_button_16x',
tooltip: 'Create a link to this report',
handler: function(b,e){
Testopia.Search.LinkPopup(values);
}
}]
}));
Ext.getCmp('object_panel').activate('case_run_search' + searchnum);
}
else{
Ext.getCmp('object_panel').add(new Testopia.TestCaseRun.List(values,{
id: 'case_run_search' + searchnum, 
closable: true,
title: 'Case-Run Search'
}));
}
Ext.getCmp('object_panel').activate('case_run_search' + searchnum);
}
}]
});
this.on('activate', this.onActivate, this);
};
Ext.extend(Testopia.Search.CaseRunsForm, Ext.Panel,{
onActivate: function(event){
if (!this.rendered){
return;
}
if (Ext.get('case_search_form')){
Ext.get('case_search_form').remove();
}
if (Ext.get('run_search_form')){
Ext.get('run_search_form').remove();
}
if (Ext.get('plan_search_form')){
Ext.get('plan_search_form').remove();
}
this.params.current_tab = 'case_run';
this.load({
url: 'tr_query.cgi',
params: this.params,
scripts: true,
text: 'Loading search form...',
callback: Testopia.Search.fillInForm.createDelegate(this,['caserun',this.params])
});
}
});
Testopia.Search.SavedReportsList = function(cfg){
this.store = new Ext.data.JsonStore({
url: 'tr_query.cgi',
listeners: { 'exception': Testopia.Util.loadError },
baseParams: {action: 'get_saved_searches', type: cfg.type},
root: 'searches',
fields: ["name","query","author","type"]
});
var ds = this.store;
var current_col = 'dashboard_leftcol';
this.columns = [
{header: "Name", width: 30, dataindex: "name", sortable: true}
];
Testopia.Search.SavedReportsList.superclass.constructor.call(this, {
id: cfg.id || "reports_grid",
loadMask: {msg: "Loading ..."},
autoScroll: true,
sm: new Ext.grid.RowSelectionModel({
singleSelect: true,
listeners: {'rowselect': function(sm, i, r){
var name = r.get('name');
if(r.get('type') == 1){
Ext.getCmp('object_panel').setActiveTab('dashboardpanel');
var newPortlet = new Ext.ux.Portlet({
title: name,
id: name,
closable: true,
autoScroll: true,
tools: PortalTools,
url: r.get('query')
});
Ext.getCmp(current_col).add(newPortlet);
Ext.getCmp(current_col).doLayout();
Testopia.Search.dashboard_urls.push(r.get('query'));
newPortlet.load({
scripts: true,
url: r.get('query')
});
current_col = current_col == 'dashboard_leftcol' ? 'dashboard_rightcol' : 'dashboard_leftcol';
}
else{
sm.grid.loadPanel(r);
}
}}
}),
viewConfig: {
forceFit:true
}
});
Ext.apply(this,cfg);
this.on('rowcontextmenu', this.onContextClick, this);
this.on('activate', this.onActivate, this);
};
Ext.extend(Testopia.Search.SavedReportsList, Ext.grid.GridPanel, {
onContextClick: function(grid, index, e){
var d = grid.store.getAt(index).get('query').match(/(tr_list_|_reports)/);
if (d){
var g = grid.store.getAt(index).get('query').match(/completion/);
if (g)
d = null;
}
this.menu = new Ext.menu.Menu({
id:'run-ctx-menu',
enableScrolling: false,
items: [{
text: 'Open in a new tab', 
disabled: d ? false : true,
handler: function(){
var r = grid.store.getAt(index);
if (r.get('type') == 0){
grid.loadPanel(r);
}
else{
var newTab = new Ext.Panel({
title: r.get('name'),
closable: true,
id: 'search' + r.get('name'),
autoScroll: true
});
Ext.getCmp('object_panel').add(newTab);
Ext.getCmp('object_panel').activate('search' + r.get('name'));
newTab.load({
url: r.get('query')
});
}
}
},{
text: 'Edit', 
icon: 'extensions/testopia/img/edit.png',
iconCls: 'img_button_16x',
disabled: d ? false : true,
handler: function(){
var r = grid.store.getAt(index);
var name = r.get('name');
var q = r.get('query');
var type;
type = q.match(/tr_list_(run|case|plan|caserun)s/);
if (!type) {
type = q.match(/tr_(run|case|plan|caserun)_reports/);
if (!type) {
Ext.Msg.show({
title: "Non-editable",
msg: "This Search or Report cannot be edited",
icon: Ext.MessageBox.ERROR,
buttons: Ext.MessageBox.OK
});
return;
}
}
type = type[1];
var params = Testopia.Util.urlQueryToJSON(r.get('query'));
Testopia.Search.Popup(type, params);
}
},{
text: 'Delete',
icon: 'extensions/testopia/img/delete.png',
iconCls: 'img_button_16x',
handler: function (){
var form = new Ext.form.BasicForm('testopia_helper_frm',{});
Ext.Msg.show({
msg: 'Are you sure you want to delete this search?',
buttons: Ext.MessageBox.YESNO,
icon: Ext.MessageBox.QUESTION,
fn: function(btn, text){
if (btn == 'yes'){
var r = grid.store.getAt(index);
form.submit({
url: 'tr_query.cgi',
params: {action: 'delete_query', query_name: r.get('name')},
success: function(){
if (grid){
grid.store.load();
}
},
failure: Testopia.Util.error
});
}
}
});
}
},{
text: 'Refresh List',
icon: 'extensions/testopia/img/refresh.png',
iconCls: 'img_button_16x',
handler: function(){
grid.store.reload();
}
}]
});
e.stopEvent();
this.menu.showAt(e.getXY());
},
onActivate: function(event){
if (!this.store.getCount()){
this.store.load();
}
},
loadPanel: function(r){
var cfg = {
id: 'search' + r.get('name'), 
closable: true,
title: r.get('name'),
lc: 'lc_' + r.get('name'),
rc: 'rc_' + r.get('name')
};
if (r.get('type') == 3){
Ext.getCmp('object_panel').add(new Testopia.Search.DashboardPanel(cfg));
Ext.getCmp('object_panel').activate('search' + r.get('name'));
Ext.getCmp('search' + r.get('name')).getTopToolbar().add({
xtype: 'button',
id: 'link_dashboard_btn',
icon: 'extensions/testopia/img/link.png',
iconCls: 'img_button_16x',
tooltip: 'Create a link to this dashboard',
handler: function(b,e){
var l = window.location;
var pathprefix = l.pathname.match(/(.*)[\/\\]([^\/\\]+\.\w+)$/);
pathprefix = pathprefix[1];
var win = new Ext.Window({
width: 300,
plain: true,
shadow: false,
items: [new Ext.form.TextField({
value: encodeURI(l.protocol + '//' + l.host + pathprefix + '/' + 'tr_show_product.cgi?dashboard=' + r.get('name') + '&userid=' + Testopia_user.id),
width: 287
})]
});
win.show();
}
});
var current_col = 'lc_' + r.get('name');
var urls = r.get('query').split('::>');
var newPortlet;
for (var i in urls){
if (typeof urls[i] != 'string'){
continue;
}
var p = Testopia.Util.urlQueryToJSON(urls[i]);
var t;
typeof p.qname == 'object' ? t = p.qname[0] : t = p.qname;
newPortlet = new Ext.ux.Portlet({
title: t || ' ',
id: 'search' + r.get('name') + i,
closable: true,
autoScroll: true,
tools: PortalTools,
url: urls[i]
});
Ext.getCmp(current_col).add(newPortlet);
Ext.getCmp(current_col).doLayout();
current_col = current_col == 'lc_' + r.get('name') ? 'rc_' + r.get('name') : 'lc_' + r.get('name');
newPortlet.load({
scripts: true,
url: urls[i]
});
}
}
else{
var params = Testopia.Util.urlQueryToJSON(r.get('query'));
var tab = params.current_tab;
switch(tab){
case 'plan':
Ext.getCmp('object_panel').add(new Testopia.TestPlan.Grid(params,cfg));
break;
case 'run':
Ext.getCmp('object_panel').add(new Testopia.TestRun.Grid(params,cfg));
break;
case 'case':
Ext.getCmp('object_panel').add(new Testopia.TestCase.Grid(params,cfg));
break;
default:
Ext.Msg.show({
title:'No Type Found',
msg: 'There must have been a problem saving this search. I can\'t find a type',
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.ERROR
});
return;
}
Ext.getCmp('object_panel').activate('search' + r.get('name'));
}
}
});
PortalTools = [{
id:'gear',
handler: function(e,target,panel){
var form = new Ext.form.BasicForm('testopia_helper_frm',{});
this.menu = new Ext.menu.Menu({
id: 'portal_tools_menu',
items: [
{
text: 'Save',
handler: function(){
Ext.Msg.prompt('Save Report As', '', function(btn, text){
if (btn == 'ok'){
form.submit({
url: 'tr_query.cgi',
params: {action: 'save_query', query_name: text, query_part: panel.url, type: 1},
success: function(){
Ext.getCmp('reports_grid').store.load();
panel.title = text;
},
failure: Testopia.Util.error
});
}
});
}
},{
text: 'Refresh',
icon: 'extensions/testopia/img/refresh.png',
iconCls: 'img_button_16x',
handler: function(){
panel.load({url: panel.url});
}
},{
text: 'Link to this report',
handler: function(){
var path;
if (panel.url.match(/^http/)){
path = panel.url;
path = path.replace(/\&noheader=1/gi, '');
}
else{
var l = window.location;
var pathprefix = l.pathname.match(/(.*)[\/\\]([^\/\\]+\.\w+)$/);
pathprefix = pathprefix[1];
path = l.protocol + '//' + l.host + pathprefix + '/' + panel.url;
path = path.replace(/\&noheader=1/gi, '');
}
var win = new Ext.Window({
width: 300,
plain: true,
shadow: false,
items: [new Ext.form.TextField({
value: path,
width: 287
})]
});
win.show();
}
},{
text: 'Delete',
handler: function(){
Ext.Msg.show({
title:'Confirm Delete?',
icon: Ext.MessageBox.QUESTION,
msg: 'Are you sure you want to delete this report?',
buttons: Ext.Msg.YESNO,
fn: function(btn, text){
if (btn == 'yes'){
form.submit({
url: 'tr_query.cgi',
params: {action: 'delete_query', query_name: panel.title},
success: function(){
Ext.getCmp('reports_grid').store.load();
panel.ownerCt.remove(panel, true);
},
failure: Testopia.Util.error
});
}
}
});
}
}]
});
e.stopEvent();
this.menu.showAt(e.getXY());
}
},{
id:'close',
handler: function(e, target, panel){
panel.ownerCt.remove(panel, true);
}
}];
Testopia.Search.LinkPopup = function(params){
if (params.current_tab == 'case_run') {
params.current_tab = 'caserun';
}
var file;
if (params.report) {
file = 'tr_' + params.current_tab + '_reports.cgi';
}
else {
file = 'tr_list_' + params.current_tab + 's.cgi';
}
var l = window.location;
var pathprefix = l.pathname.match(/(.*)[\/\\]([^\/\\]+\.\w+)$/);
pathprefix = pathprefix[1];
var win = new Ext.Window({
width: 300,
plain: true,
shadow: false,
items: [new Ext.form.TextField({
value: l.protocol + '//' + l.host + pathprefix + '/' + file + '?' + Testopia.Util.JSONToURLQuery(params, '', ['ctype']),
width: 287
})]
});
win.show();
};
ATTACHMENT_DELETE_WARNING = 'You are about to remove the selected attachments. This cannot be undone. Continue?';
CASE_CATEGORY_DELETE_WARNING = 'You are about to delete the selected test case category.  Are you sure you want to continue?';
CASE_DELETE_WARNING = 'You are about to delete the selected test cases including all children and history. This action cannot be undone. Are you sure you want to continue?';
PLAN_DELETE_WARNING = 'You are about to delete the selected test plans including all children and history. This action cannot be undone. Are you sure you want to continue?';
RUN_DELETE_WARNING = 'You are about to delete the selected test runs including all children and history. This action cannot be undone. Are you sure you want to continue?';
CASERUN_DELETE_WARNING = 'You are about to remove the selected test cases from this run including all history. This action cannot be undone. Are you sure you want to continue?';
ENVIRONMENT_DELETE_WARNING = 'You are about to delete the selected test environment including associated test case data. This action cannot be undone. Are you sure you want to continue?';
PRODUCT_PLAN_IMPORT = 'Accepts XML files under 2 MB in size. <br> See <a href="extensions/testopia/testopia.xsd" target="_blank">testopia.xsd</a> for proper format.';
PLAN_CASES_IMPORT = 'Accepts CSV and XML files under 2 MB in size. <br> See <a href="extensions/testopia/import_example.csv" target="_blank">import_example.csv</a> and <a href="extensions/testopia/testopia.xsd" target="_blank">testopia.xsd</a> for proper format.';
Testopia.Tags.Lookup = function(cfg){
Testopia.Tags.Lookup.superclass.constructor.call(this, {
id: cfg.id || 'tag_lookup',
store: new Ext.data.JsonStore({
url: 'tr_quicksearch.cgi',
listeners: { 'exception': Testopia.Util.loadError },
baseParams: {
action: 'gettag'
},
root: 'tags',
totalProperty: 'total',
fields: [{
name: 'id',
mapping: 'tag_id'
}, {
name: 'name',
mapping: 'tag_name'
}]
}),
queryParam: 'search',
loadingText: 'Looking up tags...',
displayField: 'name',
valueField: 'id',
typeAhead: false,
hiddenName: 'tag',
hideTrigger: true,
minListWidth: 300,
minChars: 2,
width: 150,
editable: true,
forceSelection: false,
emptyText: 'Type a tagname...',
listeners: {
'specialkey': function(f, e){
if (e.getKey() == e.ENTER) {
Ext.getCmp('tag_add_btn').fireEvent('click');
}
}
}
});
Ext.apply(this, cfg);
};
Ext.extend(Testopia.Tags.Lookup, Ext.form.ComboBox);
Testopia.Tags.renderer = function(v, md, r, ri, ci, s, type, pid){
return '<div style="cursor:pointer" onclick=Testopia.Tags.list("' + type + '",' + pid + ',"' + r.get('tag_name') + '")>' + v + '</div>';
};
Testopia.Tags.list = function(type, product, tag){
var cfg = {
title: 'Tag Results: ' + tag,
closable: true,
id: tag + 'search' + product,
autoScroll: true
}; 
var search = {
product_id: product,
tags: tag
};
var newTab
if (type == 'case') {
newTab = new Testopia.TestCase.Grid(search, cfg);
}
else 
if (type == 'plan') {
newTab = new Testopia.TestPlan.Grid(search, cfg);
}
else 
if (type == 'run') {
newTab = new Testopia.TestRun.Grid(search, cfg);
}
Ext.getCmp('object_panel').add(newTab);
Ext.getCmp('object_panel').activate(tag + 'search' + product);
};
Testopia.Tags.ObjectTags = function(obj, obj_id){
this.orig_id = obj_id;
this.obj_id = obj_id;
this.store = new Ext.data.JsonStore({
url: 'tr_tags.cgi',
listeners: { 'exception': Testopia.Util.loadError },
baseParams: {
action: 'gettags',
type: obj
},
root: 'tags',
id: 'tag_id',
fields: [{
name: 'tag_id',
mapping: 'tag_id'
}, {
name: 'tag_name',
mapping: 'tag_name'
}, {
name: 'run_count',
mapping: 'run_count'
}, {
name: 'case_count',
mapping: 'case_count'
}, {
name: 'plan_count',
mapping: 'plan_count'
}]
});
var ds = this.store;
this.remove = function(){
var form = new Ext.form.BasicForm('testopia_helper_frm', {});
form.submit({
url: 'tr_tags.cgi',
params: {
action: 'removetag',
type: obj,
id: this.obj_id,
tag: Testopia.Util.getSelectedObjects(Ext.getCmp(obj + 'tagsgrid'), 'tag_name')
},
success: function(){
ds.reload();
},
failure: Testopia.Util.error
});
};
this.add = function(){
var form = new Ext.form.BasicForm('testopia_helper_frm', {});
form.submit({
url: 'tr_tags.cgi',
params: {
action: 'addtag',
type: obj,
id: this.obj_id,
tag: Ext.getCmp(obj + 'tag_lookup').getRawValue()
},
success: function(){
ds.reload();
},
failure: Testopia.Util.error
});
};
this.columns = [{
dataIndex: 'tag_id',
hidden: true,
hideable: false
}, {
header: 'Name',
width: 150,
dataIndex: 'tag_name',
id: 'tag_name',
sortable: true,
hideable: false
}, {
header: 'Cases',
width: 35,
dataIndex: 'case_count',
sortable: true,
hidden: true,
renderer: Testopia.Tags.renderer.createDelegate(this, ['case'], true)
}, {
header: 'Runs',
width: 35,
dataIndex: 'run_count',
sortable: true,
hidden: true,
renderer: Testopia.Tags.renderer.createDelegate(this, ['run'], true)
}, {
header: 'Plans',
width: 35,
dataIndex: 'plan_count',
sortable: true,
hidden: true,
renderer: Testopia.Tags.renderer.createDelegate(this, ['plan'], true)
}];
var addButton = new Ext.Button({
id: 'tag_add_btn',
icon: 'extensions/testopia/img/add.png',
iconCls: 'img_button_16x',
handler: this.add.createDelegate(this)
});
var deleteButton = new Ext.Button({
icon: 'extensions/testopia/img/delete.png',
iconCls: 'img_button_16x',
handler: this.remove.createDelegate(this)
});
Testopia.Tags.ObjectTags.superclass.constructor.call(this, {
title: 'Tags',
split: true,
region: 'east',
layout: 'fit',
width: 200,
autoExpandColumn: "tag_name",
collapsible: true,
id: obj + 'tagsgrid',
loadMask: {
msg: 'Loading ' + obj + ' tags...'
},
autoScroll: true,
sm: new Ext.grid.RowSelectionModel({
singleSelect: false
}),
viewConfig: {
forceFit: true
},
tbar: [new Testopia.Tags.Lookup({
id: obj + 'tag_lookup'
}), addButton, deleteButton]
});
this.on('rowcontextmenu', this.onContextClick, this);
this.on('activate', this.onActivate, this);
};
Ext.extend(Testopia.Tags.ObjectTags, Ext.grid.GridPanel, {
onContextClick: function(grid, index, e){
if (!this.menu) { // create context menu on first right click
this.menu = new Ext.menu.Menu({
id: 'tags-ctx-menu',
enableScrolling: false,
items: [{
text: 'Remove Selected Tags', 
icon: 'extensions/testopia/img/delete.png',
iconCls: 'img_button_16x',
obj_id: this.obj_id,
handler: this.remove
}, {
text: 'Refresh List', 
icon: 'extensions/testopia/img/refresh.png',
iconCls: 'img_button_16x',
handler: function(){
grid.store.reload();
} 
}]
});
}
e.stopEvent();
if (grid.getSelectionModel().getCount() < 1) {
grid.getSelectionModel().selectRow(index);
}
this.menu.showAt(e.getXY());
},
onActivate: function(event){
if (!this.store.getCount() || this.orig_id != this.obj_id) {
this.store.load({
params: {
id: this.obj_id
}
});
}
}
});
Testopia.Tags.ProductTags = function(title, type, product_id){
var tag_id;
this.product_id = product_id;
this.store = new Ext.data.JsonStore({
url: 'tr_tags.cgi',
listeners: { 'exception': Testopia.Util.loadError },
baseParams: {
action: 'gettags',
type: type
},
root: 'tags',
id: 'tag_id',
fields: [{
name: 'tag_id',
mapping: 'tag_id'
}, {
name: 'tag_name',
mapping: 'tag_name'
}, {
name: 'run_count',
mapping: 'run_count'
}, {
name: 'case_count',
mapping: 'case_count'
}, {
name: 'plan_count',
mapping: 'plan_count'
}]
});
var ds = this.store;
this.columns = [{
header: "ID",
dataIndex: 'tag_id',
hidden: true
}, {
header: 'Name',
width: 150,
dataIndex: 'tag_name',
id: 'tag_name',
sortable: true
}, {
header: 'Cases',
width: 35,
dataIndex: 'case_count',
sortable: true,
renderer: Testopia.Tags.renderer.createDelegate(this, ['case', product_id], true)
}, {
header: 'Runs',
width: 35,
dataIndex: 'run_count',
sortable: true,
renderer: Testopia.Tags.renderer.createDelegate(this, ['run', product_id], true)
}, {
header: 'Plans',
width: 35,
dataIndex: 'plan_count',
sortable: true,
renderer: Testopia.Tags.renderer.createDelegate(this, ['plan', product_id], true)
}];
var filter = new Ext.form.TextField({
allowBlank: true,
id: 'rungrid-filter',
selectOnFocus: true
});
Testopia.Tags.ProductTags.superclass.constructor.call(this, {
title: title,
id: type + 'tags',
loadMask: {
msg: 'Loading ' + title + ' ...'
},
autoExpandColumn: "tag_name",
autoScroll: true,
sm: new Ext.grid.RowSelectionModel({
singleSelect: false
}),
viewConfig: {
forceFit: true
}
});
this.on('rowcontextmenu', this.onContextClick, this);
this.on('activate', this.onActivate, this);
};
Ext.extend(Testopia.Tags.ProductTags, Ext.grid.GridPanel, {
onContextClick: function(grid, index, e){
if (!this.menu) { // create context menu on first right click
this.menu = new Ext.menu.Menu({
id: 'tags-ctx-menu',
enableScrolling: false,
items: [{
text: 'Refresh', 
icon: 'extensions/testopia/img/refresh.png',
iconCls: 'img_button_16x',
handler: function(){
ds.reload();
}
}]
});
}
e.stopEvent();
this.menu.showAt(e.getXY());
},
onActivate: function(event){
if (!this.store.getCount()) {
this.store.load({
params: {
product_id: this.product_id
}
});
}
}
});
Testopia.Tags.update = function(type, grid){
function commitTag(action, value, grid){
var form = new Ext.form.BasicForm('testopia_helper_frm', {});
form.submit({
url: 'tr_tags.cgi',
params: {
action: action,
tag: value,
type: type,
id: Testopia.Util.getSelectedObjects(grid, type + '_id')
},
success: function(){
},
failure: Testopia.Util.error
});
}
var win = new Ext.Window({
title: 'Add or Remove Tags',
id: 'tags_edit_win',
layout: 'fit',
split: true,
plain: true,
shadow: false,
width: 350,
listeners: {'afterlayout':function(){Ext.getCmp('tags_update').focus('',10)}},
height: 150,
items: [new Ext.FormPanel({
labelWidth: '40',
bodyStyle: 'padding: 5px',
items: [new Testopia.Tags.Lookup({
id: 'tags_update',
fieldLabel: 'Tags'
})]
})],
buttons: [{
text: 'Add Tag',
handler: function(){
commitTag('addtag', Ext.getCmp('tags_update').getRawValue(), grid);
win.close();
}
}, {
text: 'Remove Tag',
handler: function(){
commitTag('removetag', Ext.getCmp('tags_update').getRawValue(), grid);
win.close();
}
}, {
text: 'Close',
handler: function(){
win.close();
}
}]
});
win.show();
};
Testopia.Util.displayStatusIcon = function(name){
return '<img src="extensions/testopia/img/' + name + '_small.gif" alt="' + name + '" title="' + name + '">';
};
Testopia.Util.makeLink = function(id, m, r, ri, ci, s, type){
if (type == 'bug') {
if (s.isTreport === true) 
return '<a href="show_bug.cgi?id=' + id + '" target="_blank">' + id + '</a>';
return '<a href="show_bug.cgi?id=' + id + '">' + id + '</a>';
}
if (s.isTreport === true) 
return '<a href="tr_show_' + type + '.cgi?' + type +'_id=' + id + '" target="_blank">' + id + '</a>';
return '<a href="tr_show_' + type +'.cgi?' + type + '_id=' + id + '">' + id + '</a>';
};
Testopia.Util.CascadeProductSelection = function(){
addOption = function(selectElement, newOption){
try {
selectElement.add(newOption, null);
} 
catch (e) {
selectElement.add(newOption, selectElement.length);
}
};
lsearch = function(val, arr){
if (typeof arr != 'object') {
if (arr == val) 
return true;
return false;
}
for (var i in arr) {
if (arr[i] == val) 
return true;
}
return false;
};
this.addOption = addOption;
var fillSelects = function(data, prods){
var s = Testopia.Util.urlQueryToJSON(window.location.search);
if (prods) {
s.product = prods;
}
for (var i in data.selectTypes) {
if (typeof data.selectTypes[i] != 'function') {
try {
document.getElementById(data.selectTypes[i]).options.length = 0;
for (var j in data[data.selectTypes[i]]) {
if (typeof data[data.selectTypes[i]][j] != 'function') {
var newOption = new Option(data[data.selectTypes[i]][j], data[data.selectTypes[i]][j], false, lsearch(data[data.selectTypes[i]][j], s[data.selectTypes[i]]));
addOption(document.getElementById(data.selectTypes[i]), newOption);
}
}
document.getElementById(data.selectTypes[i]).disabled = false;
document.getElementById(data.selectTypes[i])
} 
catch (err) {
}
}
}
};
this.fillSelects = fillSelects;
this.onProductSelection = function(prod){
var ids = [];
for (var i = 0; i < prod.options.length; i++) {
if (prod.options[i].selected === true) {
ids.push(prod.options[i].value);
}
}
var form = new Ext.form.BasicForm('testopia_helper_frm', {});
var type = prod.id == 'classification' ? 'classification' : 'product';
form.submit({
url: "tr_query.cgi",
params: {
value: ids.join(","),
action: "getversions",
type: type
},
success: function(f, a){
fillSelects(a.result.objects);
},
failure: Testopia.Util.error
});
};
return this;
};
Testopia.User.Lookup = function(cfg){
Testopia.User.Lookup.superclass.constructor.call(this, {
id: cfg.id || 'user_lookup',
store: new Ext.data.JsonStore({
url: 'tr_quicksearch.cgi',
listeners: { 'exception': Testopia.Util.loadError },
baseParams: {
action: 'getuser'
},
root: 'users',
totalProperty: 'total',
id: 'login',
fields: [{
name: 'login',
mapping: 'id'
}, {
name: 'name',
mapping: 'name'
}]
}),
listeners: {
'valid': function(f){
f.value = f.getRawValue();
},
'beforequery': function(o){
if (cfg.multistring) {
var term = o.query.match(/(^.*),(.*)/);
if (term) {
o.combo.multivalue = term[1];
o.query = term[2];
}
}
},
'select': function(c, r, i){
if (cfg.multistring) {
var v = c.multivalue || '';
v = v ? v + ', ' + r.get('login') : r.get('login');
c.setValue(v);
}
}
},
queryParam: 'search',
loadingText: 'Looking up users...',
displayField: 'login',
valueField: 'login',
typeAhead: true,
hideTrigger: true,
minListWidth: 300,
forceSelection: false,
emptyText: 'Type a username...',
pageSize: 20,
tpl: '<tpl for="."><div class="x-combo-list-item"><table><tr><td>{name}</td></tr><tr><td><b>{login}</td></tr></table></div></tpl>'
});
Ext.apply(this, cfg);
};
Ext.extend(Testopia.User.Lookup, Ext.form.ComboBox);
DocCompareToolbar = function(object, id){
var store = new Ext.data.JsonStore({
url: 'tr_history.cgi',
listeners: { 'exception': Testopia.Util.loadError },
baseParams: {
action: 'getdocversions',
object: object,
object_id: id
},
root: 'list',
fields: [{
name: 'id',
mapping: 'id'
}, {
name: 'name',
mapping: 'name'
}]
});
this.toolbar = new Ext.Toolbar({
id: 'doc_compare_tbar',
items: [        //            new Ext.form.ComboBox({
new Ext.Toolbar.Fill(), new Ext.form.ComboBox({
id: 'doc_view',
store: store,
displayField: 'name',
valueField: 'id',
width: 50,
triggerAction: 'all'
}), {
xtype: 'button',
id: 'doc_view_btn',
text: 'View Version',
handler: function(){
var tab = Ext.getCmp('object_panel').add({
title: 'Version ' + Ext.getCmp('doc_view').getValue(),
closable: true,
autoScroll: true
});
tab.show();
tab.load({
url: 'tr_history.cgi',
params: {
action: 'showdoc',
object: object,
object_id: id,
version: Ext.getCmp('doc_view').getValue()
},
failure: Testopia.Util.error
});
}
}]
});
return this.toolbar;
};
Testopia.Util.HistoryList = function(object, id){
this.store = new Ext.data.JsonStore({
url: 'tr_history.cgi',
listeners: { 'exception': Testopia.Util.loadError },
baseParams: {
action: 'show',
object: object,
object_id: id
},
root: 'list',
fields: [{
name: "what",
mapping: "what"
}, {
name: "who",
mapping: "who"
}, {
name: "oldvalue",
mapping: "oldvalue"
}, {
name: "newvalue",
mapping: "newvalue"
}, {
name: "when",
mapping: "changed"
}]
});
this.columns = [{
header: "What",
width: 150,
dataIndex: 'what',
sortable: true
}, {
header: "Who",
width: 180,
sortable: true,
dataIndex: 'who'
}, {
header: "When",
width: 150,
sortable: true,
dataIndex: 'when'
}, {
header: "Old",
width: 180,
sortable: true,
dataIndex: 'oldvalue'
}, {
id: 'new',
header: "New",
width: 180,
sortable: true,
dataIndex: 'newvalue'
}];
Testopia.Util.HistoryList.superclass.constructor.call(this, {
title: 'Change History',
id: 'history-grid',
layout: 'fit',
loadMask: {
msg: 'Loading History...'
},
autoExpandColumn: "new",
autoScroll: true,
sm: new Ext.grid.RowSelectionModel({
singleSelect: false
})
});
this.on('rowcontextmenu', this.onContextClick, this);
this.on('activate', this.onActivate, this);
};
Ext.extend(Testopia.Util.HistoryList, Ext.grid.GridPanel, {
onActivate: function(){
if (!this.store.getCount()) {
this.store.load();
}
},
onContextClick: function(grid, index, e){
if (!this.menu) { // create context menu on first right click
this.menu = new Ext.menu.Menu({
id: 'history-ctx-menu',
enableScrolling: false,
items: [{
text: 'Refresh',
icon: 'extensions/testopia/img/refresh.png',
iconCls: 'img_button_16x',
handler: function(){
grid.store.reload();
}
}]
});
}
e.stopEvent();
this.menu.showAt(e.getXY());
}
});
Testopia.Util.PagingBar = function(type, store){
this.type = type;
var baseParams = clone(store.baseParams);
function doUpdate(){
this.updateInfo();
}
function clone(orig){
var clone = new Object();
for (var i in orig) {
clone[i] = orig[i];
}
return clone;
}
function viewallUpdate(){
this.cursor = 0;
this.afterTextEl.el.innerHTML = String.format(this.afterPageText, 1);
this.field.dom.value = 1;
this.updateInfo();
}
var sizer = new Ext.form.ComboBox({
store: new Ext.data.SimpleStore({
fields: ['value', 'name'],
id: 0,
data: [[25, 25], [50, 50], [100, 100], [500, 500]],
autoLoad: true
}),
id: type + '_page_sizer',
mode: 'local',
displayField: 'name',
valueField: 'value',
triggerAction: 'all',
editable: false,
width: 50
});
sizer.on('select', function(c, r, i){
this.pageSize = r.get('value');
Ext.state.Manager.set('TESTOPIA_DEFAULT_PAGE_SIZE', r.get('value'));
store.baseParams.limit = r.get('value');
store.load({
params: {
start: 0
},
callback: doUpdate.createDelegate(this)
});
}, this);
this.sizer = sizer;
var viewall = new Ext.Button({
text: 'View All',
enableToggle: true
});
viewall.on('toggle', function(b, p){
if (p) {
this.pageSize = 0;
store.load({
params: {
viewall: 1
},
callback: viewallUpdate.createDelegate(this)
});
}
else {
this.pageSize = sizer.getValue();
store.load({
params: {
start: 0,
limit: sizer.getValue()
}
});
}
}, this);
var filter = new Ext.form.TextField({
allowBlank: true,
id: type + '_paging_filter',
selectOnFocus: true
});
filter.on('specialkey', function(f, e){
var key = e.getKey();
if (key == e.ENTER) {
var params = {
start: 0,
limit: sizer.getValue()
};
if (this.getValue().length === 0) {
store.baseParams = clone(baseParams);
store.load({
params: params
});
Ext.getCmp(type + '_filtered_txt').hide();
return;
}
var params = {
start: 0,
limit: sizer.getValue()
};
var s = this.getValue();
var term = s.match(/(^.*?):/);
if (term) {
term = term[1];
var q = Testopia.Util.trim(s.substr(s.indexOf(':') + 1, s.length));
if (term.match(/^start/i)) {
term = 'start_date';
}
if (term.match(/^stop/i)) {
term = 'stop_date';
}
if (term.match(/^manager/i)) {
term = 'manager';
}
switch (term) {
case 'status':
if (type == 'case') {
term = 'case_status';
}
else 
if (type == 'caserun') {
term = 'case_run_status';
}
else {
term = 'run_status';
if (q.match(/running/i)) {
q = 0;
}
else {
q = 1;
}
}
break;
case 'tester':
term = 'default_tester';
break;
case 'plan':
term = 'plan_id';
break;
case 'case':
term = 'case_id';
break;
case 'run':
term = 'run_id';
break;
case 'product_version':
term = 'default_product_version';
break;
}
store.baseParams[term] = q;
store.baseParams[term + '_type'] = 'substring';
}
else {
if (type == 'case' || type == 'run') {
store.baseParams.summary = this.getValue();
store.baseParams.summary_type = 'allwordssubst';
}
else 
if (type == 'caserun') {
store.baseParams.case_summary = this.getValue();
store.baseParams.case_summary_type = 'allwordssubst';
}
else {
store.baseParams.name = this.getValue();
store.baseParams.name_type = 'allwordssubst';
}
}
store.load({
params: params
});
Ext.getCmp(type + '_filtered_txt').show();
}
if ((key == e.BACKSPACE || key == e.DELETE) && this.getValue().length === 0) {
store.baseParams = baseParams;
store.load({
params: {
start: 0,
limit: sizer.getValue()
}
});
Ext.getCmp(type + '_filtered_txt').hide();
}
});
sizer.on('render', function(){
var tt = new Ext.ToolTip({
target: type + '_paging_filter',
title: 'Quick Search Filter',
hideDelay: '500',
html: "Enter column and search term separated by ':'<br> <b>Example:</b> priority: P3<br>Blank field and ENTER to clear"
});
});
Testopia.Util.PagingBar.superclass.constructor.call(this, {
id: type + '_pager',
pageSize: Ext.state.Manager.get('TESTOPIA_DEFAULT_PAGE_SIZE', 25),
displayInfo: true,
displayMsg: 'Displaying test ' + type + 's {0} - {1} of {2}',
emptyMsg: 'No test ' + type + 's were found',
store: store,
items: ['Filter: ', filter, ' ', '-', 'View ', ' ', sizer, ' ', viewall, ' ', 
{
type: 'tbtext',
text: '(FILTERED)',
hidden: true,
id: type + '_filtered_txt',
style: 'font-weight:bold;color:red'
}]
});
this.on('render', this.setPager, this);
this.cursor = 0;
};
Ext.extend(Testopia.Util.PagingBar, Ext.PagingToolbar, {
setPager: function(){
Ext.getCmp(this.type + '_page_sizer').setValue(Ext.state.Manager.get('TESTOPIA_DEFAULT_PAGE_SIZE', 25));
}
});
Testopia.Util.updateFromList = function(type, params, grid){
var form = new Ext.form.BasicForm('testopia_helper_frm', {});
params.ctype = 'json';
params.action = 'update';
form.submit({
url: 'tr_list_' + type + 's.cgi',
params: params,
success: function(f, a){
if (type == 'caserun') {
Ext.getCmp('run_progress').updateProgress(a.result.passed, a.result.failed, a.result.blocked, a.result.complete);
}
Testopia.Util.notify.msg('Test ' + type + 's updated', 'The selected {0}s were updated successfully', type);
if (grid.selectedRows) {
grid.store.baseParams.addcases = grid.selectedRows.join(',');
Ext.getCmp(type + '_filtered_txt').show();
}
try {
Ext.getCmp('case_details_panel').store.reload();
} 
catch (err) {
}
grid.store.reload({
callback: function(){
if (grid.selectedRows) {
var sm = grid.getSelectionModel();
var sel = [];
for (var i = 0; i < grid.selectedRows.length; i++) {
var index = grid.store.find('case_id', grid.selectedRows[i]);
if (index >= 0) 
sel.push(index);
}
sm.selectRows(sel);
if (sm.getCount() < 1) {
Ext.getCmp('case_details_panel').disable();
}
}
}
});
},
failure: function(f, a){
Testopia.Util.error(f, a);
grid.store.reload({
callback: function(){
if (grid.selectedRows) {
grid.getSelectionModel().selectRows(grid.selectedRows);
}
}
});
}
});
};
Testopia.Util.ComboRenderer = function(v, md, r, ri, ci, s){
f = this.getColumnModel().getCellEditor(ci, ri).field;
record = f.store.getById(v);
if (record) {
return record.data[f.displayField];
}
else {
return v;
}
};
Testopia.Util.error = function(f, a){
f.el.unmask();
var message;
if (a.response.status && a.response.status != 200) {
message = {
title: 'System Error!',
msg: a.response.responseText,
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.ERROR,
minWidth: 450
};
}
else {
message = {
title: 'An Error Has Occurred',
msg: a.result.message,
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.ERROR,
prompt: true,
value: a.result.message,
multiline: true,
minWidth: 450
};
}
Ext.Msg.show(message);
};
Testopia.Util.loadError = function(dp, errtype, a,o,r,ar,args){
var message = 'There was an error loading the data: ';
if (errtype == 'response'){
message += r.responseText; 
}
Ext.Msg.show({
title: 'An Error Has Occurred',
width: 450,
msg: message,
prompt: true,
multiline: true,
value: message,
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.ERROR
});
};
Testopia.Util.getSelectedObjects = function(grid, field){
var selections = grid.getSelectionModel().getSelections();
var arIDs = [];
var ids;
for (var i = 0; i < selections.length; i++) {
arIDs.push(selections[i].get(field));
}
ids = arIDs.join(',');
return ids;
};
Testopia.Util.editFirstSelection = function(grid){
if (grid.store.getCount() === 0) {
return;
}
var row = grid.store.indexOf(grid.getSelectionModel().getSelected());
if (row == -1){
row = 0;
}
grid.plugins[0].startEditing(row);
};
Testopia.Util.urlQueryToJSON = function(url){
url = url.replace(/.*\//, '');
var params = {};
var loc = url.split('?', 2);
var file = loc[0];
var search = loc[1] ? loc[1] : file;
var pairs = search.split('&');
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i].split('=');
if (params[pair[0]]){
if (typeof params[pair[0]] == 'object'){
params[pair[0]].push(decodeURI(pair[1]));
}
else {
params[pair[0]] = new Array(params[pair[0]]);
params[pair[0]].push(decodeURI(pair[1]));
}
}
else{
params[pair[0]] = decodeURI(pair[1]);
}
}
return params;
};
Testopia.Util.JSONToURLQuery = function(params, searchStr, drops){
searchStr = searchStr || '';
for (var key in params) {
if (drops.indexOf(key) != -1) {
continue;
}
if (typeof params[key] == 'object'){
for(i=0; i<params[key].length; i++){
searchStr = searchStr + key + '=' + encodeURI(params[key][i]) + '&';
}
}
else{
searchStr = searchStr + key + '=' + encodeURI(params[key]) + '&';
}
}
if (searchStr.lastIndexOf('&') == searchStr.length - 1) {
searchStr = searchStr.substr(0, searchStr.length - 1);
}
return searchStr;
};
Testopia.Util.notify = function(){
var msgCt;
function createBox(t, s){
return ['<div class="msg">', '<div class="x-box-tl"><div class="x-box-tr"><div class="x-box-tc"></div></div></div>', '<div class="x-box-ml"><div class="x-box-mr"><div class="x-box-mc"><h3>', t, '</h3>', s, '</div></div></div>', '<div class="x-box-bl"><div class="x-box-br"><div class="x-box-bc"></div></div></div>', '</div>'].join('');
}
return {
msg: function(title, format){
if (!msgCt) {
msgCt = Ext.DomHelper.insertFirst(document.getElementById('bugzilla-body'), {
id: 'msg-div'
}, true);
}
msgCt.alignTo(document, 't-t');
var s = String.format.apply(String, Array.prototype.slice.call(arguments, 1));
var m = Ext.DomHelper.append(msgCt, {
html: createBox(title, s)
}, true);
m.slideIn('t').pause(1).ghost("t", {
remove: true
});
},
init: function(){
return;
}
};
}();
Testopia.Util.trim = function(input){
input = input.replace(/^\s+/g, '');
input = input.replace(/\s+$/g, '');
return input;
};
Testopia.Util.PlanSelector = function(product_id, cfg){
var single = cfg.action.match('case') ? false : true;
var pg = new Testopia.TestPlan.Grid({
product_id: product_id
}, {
id: 'plan_selector_grid',
height: 300,
single: single
});
var pchooser = new Testopia.Product.Combo({
mode: 'local',
value: product_id
});
pchooser.on('select', function(c, r, i){
pg.store.baseParams = {
ctype: 'json',
product_id: r.get('id')
};
pg.store.load();
});
Testopia.Util.PlanSelector.superclass.constructor.call(this, {
items: [pg],
buttons: [{
text: 'Use Selected',
handler: function(){
var loc = cfg.action + '?plan_id=' + Testopia.Util.getSelectedObjects(pg, 'plan_id');
if (cfg.bug_id) {
loc = loc + '&bug=' + cfg.bug_id;
}
window.location = loc;
}
}]
});
pg.on('render', function(){
var items = pg.getTopToolbar().items.items;
for (var i = 0; i < items.length; i++) {
items[i].destroy();
}
pg.getTopToolbar().add('Product: ', pchooser);
pg.getSelectionModel().un('rowselect', pg.getSelectionModel().events['rowselect'].listeners[0].fn);
pg.getSelectionModel().un('rowdeselect', pg.getSelectionModel().events['rowdeselect'].listeners[0].fn);
pg.store.load();
});
}
Ext.extend(Testopia.Util.PlanSelector, Ext.Panel);
Testopia.Util.DisableTools = function(tbar, ex){
if (typeof ex != 'object'){
ex = [];
}
for (var i in tbar.items.items) {
if (ex.indexOf(tbar.items.items[i].id) != -1) {
continue;
}
try {
tbar.items.items[i].disable();
}
catch (e) {
}
}
}
